mprattoy commited on
Commit
df2b1f9
·
0 Parent(s):

Gradio UI updated

Browse files
.gradio/certificate.pem ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
3
+ TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
4
+ cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
5
+ WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
6
+ ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
7
+ MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
8
+ h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
9
+ 0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
10
+ A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
11
+ T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
12
+ B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
13
+ B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
14
+ KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
15
+ OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
16
+ jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
17
+ qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
18
+ rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
19
+ HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
20
+ hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
21
+ ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
22
+ 3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
23
+ NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
24
+ ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
25
+ TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
26
+ jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
27
+ oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
28
+ 4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
29
+ mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
30
+ emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
31
+ -----END CERTIFICATE-----
.idea/.gitignore ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ # Default ignored files
2
+ /shelf/
3
+ /workspace.xml
4
+ # Editor-based HTTP Client requests
5
+ /httpRequests/
6
+ # Datasource local storage ignored files
7
+ /dataSources/
8
+ /dataSources.local.xml
DEPLOYMENT.md ADDED
@@ -0,0 +1,366 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Deployment Guide
2
+
3
+ Complete guide for deploying your React Agent Builder to various platforms.
4
+
5
+ ---
6
+
7
+ ## 🚀 Option 1: Hugging Face Spaces (Easiest)
8
+
9
+ **Best for:** Quick deployment, free hosting, automatic HTTPS
10
+
11
+ ### Steps:
12
+
13
+ 1. **Create requirements.txt for HF compatibility:**
14
+ ```bash
15
+ uv pip compile pyproject.toml -o requirements.txt
16
+ ```
17
+
18
+ 2. **Create a `app.py` file:**
19
+ ```bash
20
+ cp gradio_app.py app.py
21
+ ```
22
+
23
+ 3. **Create account on [Hugging Face](https://huggingface.co/join)**
24
+
25
+ 4. **Create a new Space:**
26
+ - Go to https://huggingface.co/spaces
27
+ - Click "Create new Space"
28
+ - Choose "Gradio" as SDK
29
+ - Name your space
30
+
31
+ 5. **Upload files:**
32
+ - `app.py`
33
+ - `requirements.txt`
34
+ - `firebase-credentials-template.json` (rename without "template")
35
+
36
+ 6. **Add Firebase credentials as Secret:**
37
+ - Go to Settings → Repository Secrets
38
+ - Add secret named `FIREBASE_CREDENTIALS`
39
+ - Paste your Firebase JSON
40
+
41
+ 7. **Deploy!** Space will auto-build and deploy
42
+
43
+ **URL:** `https://huggingface.co/spaces/YOUR_USERNAME/SPACE_NAME`
44
+
45
+ ---
46
+
47
+ ## 🚂 Option 2: Railway (Recommended for Production)
48
+
49
+ **Best for:** Production apps, custom domains, automatic deployments
50
+
51
+ ### Steps:
52
+
53
+ 1. **Install Railway CLI:**
54
+ ```bash
55
+ npm i -g @railway/cli
56
+ # or
57
+ brew install railway
58
+ ```
59
+
60
+ 2. **Login:**
61
+ ```bash
62
+ railway login
63
+ ```
64
+
65
+ 3. **Initialize project:**
66
+ ```bash
67
+ railway init
68
+ ```
69
+
70
+ 4. **Add Firebase credentials:**
71
+ ```bash
72
+ railway variables set FIREBASE_CREDENTIALS_JSON="$(cat firebase-credentials.json)"
73
+ ```
74
+
75
+ 5. **Deploy:**
76
+ ```bash
77
+ railway up
78
+ ```
79
+
80
+ 6. **Get URL:**
81
+ ```bash
82
+ railway domain
83
+ ```
84
+
85
+ **Automatic deployments:** Railway auto-deploys on git push
86
+
87
+ **Config file** (`railway.json`):
88
+ ```json
89
+ {
90
+ "build": {
91
+ "builder": "NIXPACKS"
92
+ },
93
+ "deploy": {
94
+ "startCommand": "uv run python gradio_app.py",
95
+ "restartPolicyType": "ON_FAILURE"
96
+ }
97
+ }
98
+ ```
99
+
100
+ ---
101
+
102
+ ## 🎨 Option 3: Render
103
+
104
+ **Best for:** Free tier, simple deployment
105
+
106
+ ### Steps:
107
+
108
+ 1. **Push code to GitHub**
109
+
110
+ 2. **Go to [Render Dashboard](https://dashboard.render.com/)**
111
+
112
+ 3. **Create New Web Service**
113
+
114
+ 4. **Connect your GitHub repo**
115
+
116
+ 5. **Configure:**
117
+ - **Name:** your-agent-builder
118
+ - **Environment:** Python 3
119
+ - **Build Command:** `pip install uv && uv sync`
120
+ - **Start Command:** `uv run python gradio_app.py`
121
+
122
+ 6. **Add Environment Variables:**
123
+ - `FIREBASE_CREDENTIALS_JSON`: Paste your Firebase JSON
124
+
125
+ 7. **Deploy!**
126
+
127
+ **Free tier limits:** 750 hours/month, sleeps after 15 min inactivity
128
+
129
+ ---
130
+
131
+ ## 🐳 Option 4: Docker + Any Platform
132
+
133
+ **Best for:** Maximum control, can deploy anywhere
134
+
135
+ ### Create `Dockerfile`:
136
+
137
+ ```dockerfile
138
+ FROM python:3.12-slim
139
+
140
+ # Install uv
141
+ RUN pip install uv
142
+
143
+ # Set working directory
144
+ WORKDIR /app
145
+
146
+ # Copy project files
147
+ COPY pyproject.toml uv.lock ./
148
+ COPY gradio_app.py ./
149
+ COPY firebase-credentials.json ./
150
+
151
+ # Install dependencies
152
+ RUN uv sync
153
+
154
+ # Expose Gradio port
155
+ EXPOSE 7860
156
+
157
+ # Run the app
158
+ CMD ["uv", "run", "python", "gradio_app.py"]
159
+ ```
160
+
161
+ ### Create `.dockerignore`:
162
+
163
+ ```
164
+ .venv/
165
+ __pycache__/
166
+ *.pyc
167
+ .git/
168
+ .gitignore
169
+ README.md
170
+ ```
171
+
172
+ ### Build and Run:
173
+
174
+ ```bash
175
+ # Build image
176
+ docker build -t react-agent-builder .
177
+
178
+ # Run container
179
+ docker run -p 7860:7860 react-agent-builder
180
+ ```
181
+
182
+ ### Deploy to:
183
+ - **Google Cloud Run**
184
+ - **AWS ECS/Fargate**
185
+ - **Azure Container Instances**
186
+ - **DigitalOcean App Platform**
187
+
188
+ ---
189
+
190
+ ## ☁️ Option 5: Google Cloud Run
191
+
192
+ **Best for:** Serverless, scales to zero, pay per use
193
+
194
+ ### Steps:
195
+
196
+ 1. **Install Google Cloud CLI:**
197
+ ```bash
198
+ curl https://sdk.cloud.google.com | bash
199
+ ```
200
+
201
+ 2. **Login:**
202
+ ```bash
203
+ gcloud auth login
204
+ gcloud config set project YOUR_PROJECT_ID
205
+ ```
206
+
207
+ 3. **Build with Cloud Build:**
208
+ ```bash
209
+ gcloud builds submit --tag gcr.io/YOUR_PROJECT_ID/agent-builder
210
+ ```
211
+
212
+ 4. **Deploy:**
213
+ ```bash
214
+ gcloud run deploy agent-builder \
215
+ --image gcr.io/YOUR_PROJECT_ID/agent-builder \
216
+ --platform managed \
217
+ --region us-central1 \
218
+ --allow-unauthenticated
219
+ ```
220
+
221
+ 5. **Set Firebase credentials:**
222
+ ```bash
223
+ gcloud run services update agent-builder \
224
+ --set-env-vars FIREBASE_CREDENTIALS_JSON="$(cat firebase-credentials.json)"
225
+ ```
226
+
227
+ ---
228
+
229
+ ## 🌐 Option 6: Vercel (with Serverless Functions)
230
+
231
+ **Best for:** Static sites with API routes
232
+
233
+ Requires converting to serverless functions. Not recommended for this app (use Railway/Render instead).
234
+
235
+ ---
236
+
237
+ ## 🔧 Environment Variables
238
+
239
+ All platforms need these environment variables:
240
+
241
+ ### Required (for Firebase):
242
+ ```bash
243
+ FIREBASE_CREDENTIALS_JSON='{
244
+ "type": "service_account",
245
+ "project_id": "...",
246
+ ...
247
+ }'
248
+ ```
249
+
250
+ ### Optional:
251
+ ```bash
252
+ # Change default port
253
+ PORT=8080
254
+
255
+ # Set custom domain
256
+ GRADIO_SERVER_NAME=0.0.0.0
257
+ GRADIO_SERVER_PORT=7860
258
+
259
+ # Enable sharing
260
+ GRADIO_SHARE=false
261
+ ```
262
+
263
+ ---
264
+
265
+ ## 📊 Performance Comparison
266
+
267
+ | Platform | Setup Time | Cost | Scaling | Custom Domain |
268
+ |----------|-----------|------|---------|---------------|
269
+ | HF Spaces | 5 min | Free | Limited | Yes ($9/mo) |
270
+ | Railway | 10 min | $5/mo | Auto | Free |
271
+ | Render | 10 min | Free/$7 | Auto | Free |
272
+ | Cloud Run | 15 min | Pay-per-use | Excellent | Free |
273
+ | Docker | 20 min | Varies | Manual | Varies |
274
+
275
+ ---
276
+
277
+ ## 🔐 Security Checklist
278
+
279
+ Before deploying to production:
280
+
281
+ - [ ] Move Firebase credentials to environment variables
282
+ - [ ] Enable HTTPS (automatic on most platforms)
283
+ - [ ] Set up Firebase Security Rules
284
+ - [ ] Enable CORS if needed
285
+ - [ ] Add rate limiting
286
+ - [ ] Set up monitoring/logging
287
+ - [ ] Add error tracking (Sentry)
288
+ - [ ] Configure backups
289
+ - [ ] Set up CI/CD pipeline
290
+ - [ ] Add health check endpoint
291
+
292
+ ---
293
+
294
+ ## 🐛 Troubleshooting
295
+
296
+ ### "Module not found" error
297
+ ```bash
298
+ # Regenerate lock file
299
+ uv lock --upgrade
300
+ ```
301
+
302
+ ### "Port already in use"
303
+ ```bash
304
+ # Change port in gradio_app.py
305
+ server_port=8080
306
+ ```
307
+
308
+ ### Firebase connection fails
309
+ ```bash
310
+ # Check credentials format
311
+ cat firebase-credentials.json | jq .
312
+
313
+ # Verify environment variable
314
+ echo $FIREBASE_CREDENTIALS_JSON
315
+ ```
316
+
317
+ ### App crashes on startup
318
+ ```bash
319
+ # Check logs
320
+ railway logs # Railway
321
+ gcloud run logs read # Cloud Run
322
+ docker logs CONTAINER_ID # Docker
323
+ ```
324
+
325
+ ---
326
+
327
+ ## 🎯 Recommended Setup
328
+
329
+ **For Development:**
330
+ - Local with `uv run python gradio_app.py`
331
+ - Use mock mode (no Firebase needed)
332
+
333
+ **For Staging:**
334
+ - Hugging Face Spaces (free, easy)
335
+ - Connect to Firebase
336
+
337
+ **For Production:**
338
+ - Railway or Cloud Run
339
+ - Custom domain
340
+ - Firebase with security rules
341
+ - Monitoring enabled
342
+
343
+ ---
344
+
345
+ ## 📚 Next Steps
346
+
347
+ After deployment:
348
+
349
+ 1. **Test authentication** thoroughly
350
+ 2. **Create your first agent**
351
+ 3. **Set up monitoring** (use Railway/Cloud metrics)
352
+ 4. **Configure custom domain**
353
+ 5. **Add more models** to the dropdown
354
+ 6. **Implement agent analytics**
355
+ 7. **Add email notifications**
356
+
357
+ ---
358
+
359
+ ## 🆘 Need Help?
360
+
361
+ - Railway: https://railway.app/help
362
+ - Render: https://render.com/docs
363
+ - Cloud Run: https://cloud.google.com/run/docs
364
+ - HF Spaces: https://huggingface.co/docs/hub/spaces
365
+
366
+ Good luck with your deployment! 🚀
PROJECT_SUMMARY.md ADDED
@@ -0,0 +1,210 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # React Agent Builder - Project Summary
2
+
3
+ ## 📦 What You Have
4
+
5
+ A production-ready Gradio web application with:
6
+ - ✅ User authentication (login/registration)
7
+ - ✅ Dashboard with agent management
8
+ - ✅ React agent creation interface
9
+ - ✅ Firebase integration (with mock mode fallback)
10
+ - ✅ Modern dependency management with uv
11
+
12
+ ## 🚀 Getting Started (3 Steps)
13
+
14
+ ### 1. Install uv
15
+ ```bash
16
+ curl -LsSf https://astral.sh/uv/install.sh | sh
17
+ ```
18
+
19
+ ### 2. Install Dependencies
20
+ ```bash
21
+ uv sync
22
+ ```
23
+
24
+ ### 3. Run the App
25
+ ```bash
26
+ uv run python gradio_app.py
27
+ ```
28
+
29
+ **That's it!** Open http://localhost:7860 in your browser.
30
+
31
+ ## 📁 Files Included
32
+
33
+ | File | Purpose |
34
+ |------|---------|
35
+ | `gradio_app.py` | Main application code |
36
+ | `pyproject.toml` | Project configuration & dependencies |
37
+ | `uv.lock` | Locked dependencies for reproducibility |
38
+ | `README.md` | Comprehensive documentation |
39
+ | `QUICKSTART.md` | Quick reference guide |
40
+ | `firebase-credentials-template.json` | Template for Firebase setup |
41
+ | `.gitignore` | Git ignore rules |
42
+
43
+ ## 🎯 Key Features
44
+
45
+ ### Authentication System
46
+ - Secure password hashing
47
+ - Session management
48
+ - Input validation
49
+ - Works with or without Firebase
50
+
51
+ ### Dashboard
52
+ - Large, prominent "Create React Agent" button (with plus icon)
53
+ - List of all created agents
54
+ - Refresh functionality
55
+ - Clean, modern UI
56
+
57
+ ### Agent Creation
58
+ 1. **Agent Name** - Text input field
59
+ 2. **Model Selection** - Dropdown with:
60
+ - GPT-4 Turbo
61
+ - GPT-4
62
+ - GPT-3.5 Turbo
63
+ 3. **System Context Prompt** - Large text area
64
+ 4. **Submit Button** - Creates and saves agent
65
+ 5. **URL Generation** - Unique URL for each agent
66
+
67
+ ### Data Storage
68
+ - Firebase Firestore integration
69
+ - Mock mode for development/testing
70
+ - Automatic user and agent data management
71
+
72
+ ## 🔧 Configuration
73
+
74
+ ### Add More Models
75
+ Edit `gradio_app.py`, find the model dropdown:
76
+ ```python
77
+ model_dropdown = gr.Dropdown(
78
+ choices=[
79
+ "gpt-4-turbo",
80
+ "gpt-4",
81
+ "gpt-3.5-turbo",
82
+ "gpt-4o", # Add here
83
+ "gpt-3.5-turbo-16k", # Add here
84
+ ],
85
+ ...
86
+ )
87
+ ```
88
+
89
+ ### Firebase Setup (Optional)
90
+ 1. Go to [Firebase Console](https://console.firebase.google.com/)
91
+ 2. Create a project
92
+ 3. Download service account credentials
93
+ 4. Save as `firebase-credentials.json`
94
+ 5. Enable Firestore and Authentication
95
+
96
+ **Note:** App works perfectly without Firebase in mock mode!
97
+
98
+ ## 🎨 UI Design
99
+
100
+ The app features:
101
+ - Clean, modern interface
102
+ - Responsive design
103
+ - Custom CSS styling
104
+ - Tab-based navigation
105
+ - Professional color scheme (gradient buttons)
106
+ - Large, accessible buttons
107
+ - Clear form layouts
108
+
109
+ ## 📊 Database Structure
110
+
111
+ ### Users Collection
112
+ ```
113
+ users/{uid}
114
+ - username: string
115
+ - email: string
116
+ - created_at: timestamp
117
+ ```
118
+
119
+ ### Agents Collection
120
+ ```
121
+ agents/{agent_id}
122
+ - agent_id: string
123
+ - agent_name: string
124
+ - model_name: string
125
+ - system_prompt: string
126
+ - created_by: string (email)
127
+ - created_at: string
128
+ - agent_url: string
129
+ ```
130
+
131
+ ## 🛠️ Development Workflow
132
+
133
+ ### Add Dependencies
134
+ ```bash
135
+ uv add package-name
136
+ ```
137
+
138
+ ### Update Dependencies
139
+ ```bash
140
+ uv lock --upgrade
141
+ ```
142
+
143
+ ### Run with Auto-reload
144
+ ```bash
145
+ uv run gradio gradio_app.py
146
+ ```
147
+
148
+ ## 🌐 Deployment Options
149
+
150
+ ### Hugging Face Spaces
151
+ ```bash
152
+ uv pip compile pyproject.toml -o requirements.txt
153
+ # Upload to HF Spaces
154
+ ```
155
+
156
+ ### Railway / Render
157
+ - Push to Git
158
+ - Set start command: `uv run python gradio_app.py`
159
+ - Deploy!
160
+
161
+ ### Docker
162
+ ```dockerfile
163
+ FROM python:3.12
164
+ RUN pip install uv
165
+ COPY . /app
166
+ WORKDIR /app
167
+ RUN uv sync
168
+ CMD ["uv", "run", "python", "gradio_app.py"]
169
+ ```
170
+
171
+ ## 🔐 Security Features
172
+
173
+ - Password hashing (SHA-256)
174
+ - Session management
175
+ - Input validation
176
+ - Firebase security rules (when enabled)
177
+ - Protected routes
178
+ - CSRF protection (via Gradio)
179
+
180
+ ## ⚡ Why uv?
181
+
182
+ - **10-100x faster** than pip
183
+ - **Single lock file** for reproducibility
184
+ - **Disk efficient** with global cache
185
+ - **Python version management** included
186
+ - **Modern tooling** for Python projects
187
+
188
+ ## 📚 Learn More
189
+
190
+ - [uv Documentation](https://docs.astral.sh/uv/)
191
+ - [Gradio Documentation](https://www.gradio.app/docs/)
192
+ - [Firebase Documentation](https://firebase.google.com/docs)
193
+
194
+ ## 🆘 Troubleshooting
195
+
196
+ **App won't start?**
197
+ ```bash
198
+ uv sync --reinstall
199
+ ```
200
+
201
+ **Firebase errors?**
202
+ - Check `firebase-credentials.json` path
203
+ - Or just use mock mode (no Firebase needed!)
204
+
205
+ **Port already in use?**
206
+ Edit `gradio_app.py` and change `server_port=7860` to another port.
207
+
208
+ ## 🎉 You're All Set!
209
+
210
+ Your Gradio app with authentication and agent creation is ready to go. Happy building!
QUICKSTART.md ADDED
@@ -0,0 +1,57 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Quick Start Guide
2
+
3
+ ## Installation & Setup (30 seconds)
4
+
5
+ 1. **Install uv** (if not already installed):
6
+ ```bash
7
+ curl -LsSf https://astral.sh/uv/install.sh | sh
8
+ ```
9
+
10
+ 2. **Install dependencies**:
11
+ ```bash
12
+ uv sync
13
+ ```
14
+
15
+ 3. **Run the app**:
16
+ ```bash
17
+ uv run python gradio_app.py
18
+ ```
19
+
20
+ That's it! The app will open at http://localhost:7860
21
+
22
+ ## Common Commands
23
+
24
+ ```bash
25
+ # Add a new package
26
+ uv add package-name
27
+
28
+ # Update dependencies
29
+ uv lock --upgrade
30
+
31
+ # Run Python scripts
32
+ uv run python script.py
33
+
34
+ # Activate virtual environment
35
+ source .venv/bin/activate # Unix
36
+ .venv\Scripts\activate # Windows
37
+ ```
38
+
39
+ ## Firebase Setup (Optional)
40
+
41
+ For production use with Firebase:
42
+
43
+ 1. Get Firebase credentials from [Firebase Console](https://console.firebase.google.com/)
44
+ 2. Save as `firebase-credentials.json`
45
+ 3. Enable Firestore and Authentication
46
+
47
+ For development, the app works in mock mode without Firebase.
48
+
49
+ ## Why uv?
50
+
51
+ - ⚡ **10-100x faster** than pip
52
+ - 🔒 **Reproducible builds** with lock file
53
+ - 🎯 **Single tool** for all Python project needs
54
+ - 💾 **Disk space efficient** with global cache
55
+ - 🐍 **Python version management** built-in
56
+
57
+ Learn more: https://docs.astral.sh/uv/
README.md ADDED
@@ -0,0 +1,347 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # React Agent Builder - Gradio App
2
+
3
+ A complete Gradio web application with authentication and React agent creation functionality.
4
+
5
+ ## Features
6
+
7
+ ✅ **User Authentication**
8
+ - Registration page with validation
9
+ - Login page with session management
10
+ - Secure password hashing
11
+
12
+ ✅ **Dashboard**
13
+ - Clean interface with large "Create React Agent" button
14
+ - View all created agents
15
+ - Refresh agent list
16
+
17
+ ✅ **Agent Creation**
18
+ - Agent name input
19
+ - Model selection (GPT-4o, GPT-4o-mini)
20
+ - System context prompt editor
21
+ - Firebase integration for data storage
22
+ - Unique URL generation for each agent
23
+
24
+ ## Setup Instructions
25
+
26
+ ### Prerequisites
27
+
28
+ This project uses [uv](https://github.com/astral-sh/uv) for dependency management. Install it first:
29
+
30
+ ```bash
31
+ # On macOS and Linux
32
+ curl -LsSf https://astral.sh/uv/install.sh | sh
33
+
34
+ # On Windows
35
+ powershell -c "irm https://astral.sh/uv/install.ps1 | iex"
36
+
37
+ # Or with pip
38
+ pip install uv
39
+ ```
40
+
41
+ ### 1. Install Dependencies
42
+
43
+ Using uv, dependencies are automatically managed:
44
+
45
+ ```bash
46
+ # Clone or navigate to the project directory
47
+ cd gradio-react-agent
48
+
49
+ # Install dependencies (uv will handle everything)
50
+ uv sync
51
+ ```
52
+
53
+ This will create a virtual environment and install all required packages from `pyproject.toml`.
54
+
55
+ ### 2. Configure Firebase
56
+
57
+ #### Option A: Use Firebase (Production)
58
+
59
+ 1. Go to [Firebase Console](https://console.firebase.google.com/)
60
+ 2. Create a new project or select existing one
61
+ 3. Go to Project Settings → Service Accounts
62
+ 4. Click "Generate New Private Key"
63
+ 5. Save the JSON file as `firebase-credentials.json` in the project directory
64
+ 6. Enable Firestore Database and Authentication in Firebase Console
65
+
66
+ #### Option B: Use Mock Mode (Development)
67
+
68
+ The app works without Firebase in mock mode for testing. Just run it and it will use in-memory storage.
69
+
70
+ ### 3. Run the Application
71
+
72
+ Using uv:
73
+
74
+ ```bash
75
+ # Run with uv
76
+ uv run python gradio_app.py
77
+
78
+ # Or activate the virtual environment and run directly
79
+ source .venv/bin/activate # On Windows: .venv\Scripts\activate
80
+ python gradio_app.py
81
+ ```
82
+
83
+ The app will launch at `http://localhost:7860`
84
+
85
+ ## Usage Guide
86
+
87
+ ### Registration
88
+ 1. Navigate to the "Register" tab
89
+ 2. Fill in username, email, and password
90
+ 3. Click "Register"
91
+ 4. Switch to "Login" tab
92
+
93
+ ### Login
94
+ 1. Enter your email and password
95
+ 2. Click "Login"
96
+ 3. You'll be redirected to the Dashboard
97
+
98
+ ### Create React Agent
99
+ 1. Click the big "➕ Create React Agent" button
100
+ 2. Fill in:
101
+ - **Agent Name**: Give your agent a descriptive name
102
+ - **Model Name**: Choose from GPT-4 Turbo, GPT-4, or GPT-3.5 Turbo
103
+ - **System Context Prompt**: Define how your agent should behave
104
+ 3. Click "✅ Submit & Create Agent"
105
+ 4. Copy the generated Agent URL
106
+
107
+ ### View Your Agents
108
+ - All created agents appear in the "Your Agents" section
109
+ - Click "🔄 Refresh List" to update the list
110
+
111
+ ## Project Structure
112
+
113
+ ```
114
+ react-agent-builder/
115
+ ├── gradio_app.py # Main application
116
+ ├── pyproject.toml # Project config & dependencies
117
+ ├── uv.lock # Lock file for reproducible builds
118
+ ├── firebase-credentials.json # Firebase config (you create this)
119
+ ├── firebase-credentials-template.json # Template for Firebase config
120
+ └── README.md # Documentation
121
+ ```
122
+
123
+ ## Dependency Management with uv
124
+
125
+ ### Add New Dependencies
126
+
127
+ ```bash
128
+ # Add a new package
129
+ uv add package-name
130
+
131
+ # Add a development dependency
132
+ uv add --dev package-name
133
+
134
+ # Add a specific version
135
+ uv add package-name==1.2.3
136
+ ```
137
+
138
+ ### Update Dependencies
139
+
140
+ ```bash
141
+ # Update all dependencies
142
+ uv lock --upgrade
143
+
144
+ # Update a specific package
145
+ uv lock --upgrade-package package-name
146
+ ```
147
+
148
+ ### Remove Dependencies
149
+
150
+ ```bash
151
+ uv remove package-name
152
+ ```
153
+
154
+ ### View Installed Packages
155
+
156
+ ```bash
157
+ uv pip list
158
+ ```
159
+
160
+ #### Option A: Use Firebase (Production)
161
+
162
+ 1. Go to [Firebase Console](https://console.firebase.google.com/)
163
+ 2. Create a new project or select existing one
164
+ 3. Go to Project Settings → Service Accounts
165
+ 4. Click "Generate New Private Key"
166
+ 5. Save the JSON file as `firebase-credentials.json` in the project directory
167
+ 6. Enable Firestore Database and Authentication in Firebase Console
168
+
169
+ #### Option B: Use Mock Mode (Development)
170
+
171
+ The app works without Firebase in mock mode for testing. Just run it and it will use in-memory storage.
172
+
173
+ ### 3. Run the Application
174
+
175
+ ```bash
176
+ python gradio_app.py
177
+ ```
178
+
179
+ The app will launch at `http://localhost:7860`
180
+
181
+ ## Usage Guide
182
+
183
+ ### Registration
184
+ 1. Navigate to the "Register" tab
185
+ 2. Fill in username, email, and password
186
+ 3. Click "Register"
187
+ 4. Switch to "Login" tab
188
+
189
+ ### Login
190
+ 1. Enter your email and password
191
+ 2. Click "Login"
192
+ 3. You'll be redirected to the Dashboard
193
+
194
+ ### Create React Agent
195
+ 1. Click the big "➕ Create React Agent" button
196
+ 2. Fill in:
197
+ - **Agent Name**: Give your agent a descriptive name
198
+ - **Model Name**: Choose from GPT-4 Turbo, GPT-4, or GPT-3.5 Turbo
199
+ - **System Context Prompt**: Define how your agent should behave
200
+ 3. Click "✅ Submit & Create Agent"
201
+ 4. Copy the generated Agent URL
202
+
203
+ ### View Your Agents
204
+ - All created agents appear in the "Your Agents" section
205
+ - Click "🔄 Refresh List" to update the list
206
+
207
+ ## Firebase Database Structure
208
+
209
+ ### Collections
210
+
211
+ **users**
212
+ ```json
213
+ {
214
+ "uid": {
215
+ "username": "string",
216
+ "email": "string",
217
+ "created_at": "timestamp"
218
+ }
219
+ }
220
+ ```
221
+
222
+ **agents**
223
+ ```json
224
+ {
225
+ "agent_id": {
226
+ "agent_id": "string",
227
+ "agent_name": "string",
228
+ "model_name": "string",
229
+ "system_prompt": "string",
230
+ "created_by": "string (user email)",
231
+ "created_at": "timestamp",
232
+ "agent_url": "string"
233
+ }
234
+ }
235
+ ```
236
+
237
+ ## Configuration Options
238
+
239
+ ### Customize Models
240
+
241
+ Edit the `model_dropdown` choices in the code:
242
+
243
+ ```python
244
+ model_dropdown = gr.Dropdown(
245
+ choices=[
246
+ "gpt-4-turbo",
247
+ "gpt-4",
248
+ "gpt-3.5-turbo",
249
+ "gpt-4o", # Add new models here
250
+ ],
251
+ ...
252
+ )
253
+ ```
254
+
255
+ ### Customize Agent URL
256
+
257
+ Modify the `agent_url` generation in the `create_agent` function:
258
+
259
+ ```python
260
+ 'agent_url': f"https://your-domain.com/agent/{agent_id}"
261
+ ```
262
+
263
+ ## Security Notes
264
+
265
+ 🔒 **Important Security Considerations:**
266
+
267
+ 1. **Password Storage**: Passwords are hashed using SHA-256 in mock mode. In production with Firebase, use Firebase Auth's built-in security.
268
+
269
+ 2. **Session Management**: Sessions are stored in-memory. For production, use a proper session store (Redis, database).
270
+
271
+ 3. **HTTPS**: Always use HTTPS in production to encrypt data in transit.
272
+
273
+ 4. **Firebase Rules**: Set up proper Firestore security rules:
274
+
275
+ ```javascript
276
+ rules_version = '2';
277
+ service cloud.firestore {
278
+ match /databases/{database}/documents {
279
+ match /users/{userId} {
280
+ allow read, write: if request.auth != null && request.auth.uid == userId;
281
+ }
282
+ match /agents/{agentId} {
283
+ allow read: if request.auth != null;
284
+ allow write: if request.auth != null;
285
+ }
286
+ }
287
+ }
288
+ ```
289
+
290
+ ## Deployment
291
+
292
+ ### Deploy to Hugging Face Spaces
293
+
294
+ 1. Create a new Space on Hugging Face
295
+ 2. Add a `requirements.txt` file for Hugging Face compatibility:
296
+ ```bash
297
+ uv pip compile pyproject.toml -o requirements.txt
298
+ ```
299
+ 3. Upload all files including `requirements.txt`
300
+ 4. Add Firebase credentials as a Secret
301
+ 5. The app will automatically deploy
302
+
303
+ ### Deploy with uv on Cloud Platforms
304
+
305
+ For platforms that support uv:
306
+
307
+ 1. Ensure `pyproject.toml` and `uv.lock` are in your repository
308
+ 2. Set the start command to: `uv run python gradio_app.py`
309
+ 3. The platform will automatically install dependencies using uv
310
+
311
+ Compatible with:
312
+ - Railway (supports uv natively)
313
+ - Render
314
+ - Google Cloud Run
315
+ - AWS Lambda (with custom runtime)
316
+ - Azure Functions
317
+
318
+ ## Troubleshooting
319
+
320
+ ### Firebase Connection Issues
321
+ - Verify credentials file path
322
+ - Check Firebase project configuration
323
+ - Ensure Firestore and Auth are enabled
324
+
325
+ ### Mock Mode
326
+ - If Firebase credentials are not found, the app runs in mock mode
327
+ - Data is stored in memory and will be lost on restart
328
+ - Perfect for testing and development
329
+
330
+ ## Features to Add
331
+
332
+ Potential enhancements:
333
+ - [ ] Email verification
334
+ - [ ] Password reset functionality
335
+ - [ ] Agent editing/deletion
336
+ - [ ] Agent analytics dashboard
337
+ - [ ] Team collaboration features
338
+ - [ ] API key management
339
+ - [ ] Agent deployment options
340
+
341
+ ## License
342
+
343
+ MIT License
344
+
345
+ ## Support
346
+
347
+ For issues or questions, please create an issue in the repository.
__pycache__/database.cpython-312.pyc ADDED
Binary file (14 kB). View file
 
database.py ADDED
@@ -0,0 +1,376 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import email
2
+ import os
3
+ import hashlib
4
+ from datetime import datetime
5
+ import firebase_admin
6
+ from firebase_admin import credentials, firestore, auth as firebase_auth
7
+
8
+ # Initialize Firebase
9
+ FIREBASE_ENABLED = False
10
+ db = None
11
+
12
+ try:
13
+ cred = credentials.Certificate('firebase-credentials.json')
14
+ firebase_admin.initialize_app(cred)
15
+ db = firestore.client()
16
+ FIREBASE_ENABLED = True
17
+ print("Firebase initialized successfully!")
18
+ except Exception as e:
19
+ print(f"Firebase not configured. Using mock mode. Error: {e}")
20
+ db = None
21
+
22
+ # Mock databases for development/testing
23
+ mock_users = {}
24
+ mock_agents = {}
25
+ mock_workspaces = {}
26
+
27
+ # Default workspace ID (same for all users)
28
+ DEFAULT_WORKSPACE_ID = "q7KfX2rP9Wb83hNa64RmTpUiAZ0vL3dS"
29
+
30
+
31
+ def hash_password(password):
32
+ """Hash password for storage"""
33
+ return hashlib.sha256(password.encode()).hexdigest()
34
+
35
+
36
+ def generate_workspace_data(user_id, workspace_id):
37
+ """
38
+ Generate workspace data with shareScript
39
+ """
40
+ share_script = f'''<script> (function (w, d) {{ w.CLIENT_IDENTIFIER = "{user_id}"; w.WORKSPACE_IDENTIFIER = '{workspace_id}'; w.AVATAR_IMAGE_URL = 'https://firebasestorage.googleapis.com/v0/b/curious-learner-3845a.appspot.com/o/avatars%2Fchatbot.png?alt=media&token=7d937685-197b-4947-b9f9-3c05f0271d20'; w.CHATBOT_IDENTIFIER = ''; var h = d.head || d.getElementsByTagName("head")[0]; var s = d.createElement('script'); s.setAttribute('type', 'text/javascript'); s.async = true; s.setAttribute('src', 'https://curious-learner-chatbot.web.app/client.js'); h.appendChild(s); }})(window, document); </script>'''
41
+
42
+ return {
43
+ 'chatbotType': 'widget',
44
+ 'id': workspace_id,
45
+ 'shareScript': share_script,
46
+ 'workspaceName': 'Default Workspace'
47
+ }
48
+
49
+
50
+ def register_user(username, email, password):
51
+ """
52
+ Register a new user in Firebase
53
+ Returns: (success: bool, message: str, user_id: str or None)
54
+ """
55
+ try:
56
+ if FIREBASE_ENABLED:
57
+ # Create user in Firebase Auth
58
+ user = firebase_auth.create_user(
59
+ email=email,
60
+ password=password,
61
+ display_name=username
62
+ )
63
+
64
+ # Store user data in g_users collection
65
+ user_data = {
66
+ 'name': username,
67
+ 'email': email,
68
+ 'created_at': firestore.SERVER_TIMESTAMP
69
+ }
70
+ db.collection('g_users').document(user.uid).set(user_data)
71
+
72
+ # Create default workspace as subcollection inside user's document
73
+ # Path: g_users/{user_id}/workspaces/{DEFAULT_WORKSPACE_ID}
74
+ workspace_data = generate_workspace_data(user.uid, DEFAULT_WORKSPACE_ID)
75
+ workspace_data['timestamp'] = firestore.SERVER_TIMESTAMP
76
+ db.collection('g_users').document(user.uid).collection('workspaces').document(DEFAULT_WORKSPACE_ID).set(
77
+ workspace_data)
78
+
79
+ return True, "Registration successful!", user.uid
80
+ else:
81
+ # Mock registration
82
+ if email in mock_users:
83
+ return False, "User already exists!", None
84
+
85
+ user_id = hashlib.sha256(f"{email}{datetime.now()}".encode()).hexdigest()[:28]
86
+
87
+ workspace_data = generate_workspace_data(user_id, DEFAULT_WORKSPACE_ID)
88
+ workspace_data['timestamp'] = datetime.now()
89
+
90
+ mock_users[email] = {
91
+ 'user_id': user_id,
92
+ 'name': username,
93
+ 'email': email,
94
+ 'password': hash_password(password),
95
+ 'created_at': datetime.now(),
96
+ 'workspaces': {
97
+ DEFAULT_WORKSPACE_ID: workspace_data
98
+ }
99
+ }
100
+
101
+ return True, "Registration successful!", user_id
102
+
103
+ except Exception as e:
104
+ return False, f"Registration failed: {str(e)}", None
105
+
106
+
107
+ def login_user(email, password):
108
+ """
109
+ Login user
110
+ Returns: (success: bool, message: str, user_id: str or None)
111
+ """
112
+ try:
113
+ if FIREBASE_ENABLED:
114
+ # In production, you'd verify with Firebase Auth
115
+ # For Gradio, we'll use a simplified approach
116
+ users = db.collection('g_users').where('email', '==', email).limit(1).get()
117
+ if users:
118
+ user_doc = list(users)[0]
119
+ user_id = user_doc.id
120
+ return True, "Login successful!", user_id
121
+ else:
122
+ return False, "Invalid credentials!", None
123
+ else:
124
+ # Mock login
125
+ if email in mock_users:
126
+ user_data = mock_users[email]
127
+ if user_data['password'] == hash_password(password):
128
+ return True, "Login successful!", user_data['user_id']
129
+ return False, "Invalid credentials!", None
130
+
131
+ except Exception as e:
132
+ return False, f"Login failed: {str(e)}", None
133
+
134
+
135
+ def generate_chatbot_share_script(user_id, workspace_id, chatbot_id):
136
+ """
137
+ Generate shareScript for chatbot
138
+ """
139
+ return f'''<script> (function (w, d) {{ w.CLIENT_IDENTIFIER = "{user_id}"; w.WORKSPACE_IDENTIFIER = '{workspace_id}'; w.AVATAR_IMAGE_URL = 'https://firebasestorage.googleapis.com/v0/b/curious-learner-3845a.appspot.com/o/avatars%2Ffemale_profile.png?alt=media&token=58bf4a74-24c8-41b1-b8bd-e381b798bb8d'; w.CHATBOT_IDENTIFIER = '{chatbot_id}'; var h = d.head || d.getElementsByTagName("head")[0]; var s = d.createElement('script'); s.setAttribute('type', 'text/javascript'); s.async = true; s.setAttribute('src', 'https://curious-learner-chatbot.web.app/client.js'); h.appendChild(s); }})(window, document); </script>'''
140
+
141
+
142
+ def generate_chatbot_data(user_id, workspace_id, chatbot_id, chatbot_name, model_name, mcp_github_enabled, github_token,
143
+ system_prompt):
144
+ """
145
+ Generate chatbot document data with agent configuration
146
+ """
147
+ # Build MCP config for chatMessageModels
148
+ mcp_config = {}
149
+ if mcp_github_enabled and github_token:
150
+ mcp_config["github"] = {
151
+ "url": "https://api.githubcopilot.com/mcp/",
152
+ "transport": "streamable_http",
153
+ "headers": {
154
+ "Authorization": f"Bearer {github_token}"
155
+ }
156
+ }
157
+
158
+ # Agent chat message model
159
+ agent_message_model = {
160
+ 'chatMessageType': 'agent',
161
+ 'chatMessage': 'Hi I am a GitHub MCP server bot, how can I help you today?',
162
+ 'llm': {
163
+ 'provider': 'openai',
164
+ 'model': model_name
165
+ },
166
+ 'mcp': mcp_config,
167
+ 'systemPrompt': system_prompt,
168
+ 'label': '',
169
+ 'iconPath': '',
170
+ 'errorText': '',
171
+ 'validationRegex': '',
172
+ 'switchButtonEntities': [
173
+ {
174
+ 'title': 'Back Button',
175
+ 'value': True,
176
+ 'isDisabled': False
177
+ },
178
+ {
179
+ 'title': 'Skip Button',
180
+ 'value': True,
181
+ 'isDisabled': False
182
+ }
183
+ ],
184
+ 'optionEntities': []
185
+ }
186
+
187
+ return {
188
+ 'chatMessageModels': [agent_message_model],
189
+ 'chatbotName': chatbot_name,
190
+ 'chatbotType': 'widget',
191
+ 'designModel': {
192
+ 'avatarModel': {
193
+ 'avatarType': 'asset',
194
+ 'value': 'asset/image/female_profile.png'
195
+ },
196
+ 'branding': True,
197
+ 'position': 'bottomRight',
198
+ 'primaryColor': 4287203839,
199
+ 'themeColor': 4294967295,
200
+ 'welcomeMessage': True
201
+ },
202
+ 'id': chatbot_id,
203
+ 'shareScript': generate_chatbot_share_script(user_id, workspace_id, chatbot_id)
204
+ }
205
+
206
+
207
+ def create_agent(user_id, agent_name, model_name, mcp_github_enabled, github_token, system_prompt):
208
+ """
209
+ Create a new React agent
210
+ Returns: (success: bool, message: str, agent_url: str or None)
211
+ """
212
+ if not user_id:
213
+ return False, "Please login first!", None
214
+
215
+ if not agent_name or not model_name or not system_prompt:
216
+ return False, "Agent name, model, and system prompt are required!", None
217
+
218
+ # Validate GitHub token if GitHub MCP is enabled
219
+ if mcp_github_enabled and not github_token:
220
+ return False, "GitHub token is required when GitHub MCP is enabled!", None
221
+
222
+ try:
223
+ agent_id = hashlib.sha256(f"{agent_name}{user_id}{datetime.now()}".encode()).hexdigest()[:12]
224
+
225
+ # Generate unique chatbot ID (UUID format)
226
+ import uuid
227
+ chatbot_id = str(uuid.uuid1())
228
+
229
+ # Build MCP config
230
+ mcp_config = {}
231
+ if mcp_github_enabled:
232
+ mcp_config["github"] = {
233
+ "url": "https://api.githubcopilot.com/mcp/",
234
+ "transport": "streamable_http",
235
+ "headers": {
236
+ "Authorization": f"Bearer {github_token}"}
237
+ }
238
+
239
+ agent_data = {
240
+ 'agent_id': agent_id,
241
+ 'agent_name': agent_name,
242
+ 'model_name': model_name,
243
+ 'mcp_config': mcp_config,
244
+ 'github_token': github_token if mcp_github_enabled else None,
245
+ 'system_prompt': system_prompt,
246
+ 'created_by': user_id,
247
+ 'created_at': firestore.SERVER_TIMESTAMP if FIREBASE_ENABLED else datetime.now().isoformat(),
248
+ 'agent_url': f"https://curious-learner-chatbot.web.app/#/chats?clientId={user_id}&workspaceId={DEFAULT_WORKSPACE_ID}&chatbotId={chatbot_id}",
249
+ 'chatbot_id': chatbot_id
250
+ }
251
+
252
+ # Generate chatbot document data with agent configuration
253
+ chatbot_data = generate_chatbot_data(
254
+ user_id,
255
+ DEFAULT_WORKSPACE_ID,
256
+ chatbot_id,
257
+ agent_name,
258
+ model_name,
259
+ mcp_github_enabled,
260
+ github_token,
261
+ system_prompt
262
+ )
263
+
264
+ if FIREBASE_ENABLED:
265
+ # Save agent to agents collection
266
+ db.collection('agents').document(agent_id).set(agent_data)
267
+
268
+ # Create chatbot document inside workspace
269
+ # Path: g_users/{user_id}/workspaces/{DEFAULT_WORKSPACE_ID}/chatbots/{chatbot_id}
270
+ chatbot_data['timestamp'] = firestore.SERVER_TIMESTAMP
271
+ db.collection('g_users').document(user_id).collection('workspaces').document(
272
+ DEFAULT_WORKSPACE_ID).collection('chatbots').document(chatbot_id).set(chatbot_data)
273
+ else:
274
+ mock_agents[agent_id] = agent_data
275
+
276
+ # Store chatbot in mock workspace
277
+ for user_email, user_data in mock_users.items():
278
+ if user_data['user_id'] == user_id:
279
+ if 'chatbots' not in user_data['workspaces'][DEFAULT_WORKSPACE_ID]:
280
+ user_data['workspaces'][DEFAULT_WORKSPACE_ID]['chatbots'] = {}
281
+ chatbot_data['timestamp'] = datetime.now()
282
+ user_data['workspaces'][DEFAULT_WORKSPACE_ID]['chatbots'][chatbot_id] = chatbot_data
283
+ break
284
+
285
+ success_msg = f"✅ Agent '{agent_name}' created successfully!"
286
+ return True, success_msg, chatbot_id
287
+
288
+ except Exception as e:
289
+ return False, f"Failed to create agent: {str(e)}", None
290
+
291
+
292
+ def get_user_agents(user_id):
293
+ """
294
+ Get all agents/chatbots created by a user
295
+ Returns: list of agent info strings
296
+ """
297
+ if not user_id:
298
+ return []
299
+
300
+ try:
301
+ if FIREBASE_ENABLED:
302
+ # Fetch chatbots from the workspace subcollection
303
+ # Path: g_users/{user_id}/workspaces/{DEFAULT_WORKSPACE_ID}/chatbots
304
+ chatbots = db.collection('g_users').document(user_id).collection('workspaces').document(
305
+ DEFAULT_WORKSPACE_ID).collection('chatbots').get()
306
+ agent_list = []
307
+ for chatbot in chatbots:
308
+ data = chatbot.to_dict()
309
+ chatbot_id = data.get('id', chatbot.id)
310
+ chatbot_name = data.get('chatbotName', 'Unnamed Agent')
311
+ agent_url = f"https://curious-learner-chatbot.web.app/#/chats?clientId={user_id}&workspaceId={DEFAULT_WORKSPACE_ID}&chatbotId={chatbot_id}"
312
+ agent_list.append(f"• {chatbot_name}\n {agent_url}")
313
+ return agent_list
314
+ else:
315
+ agent_list = []
316
+ for user_email, user_data in mock_users.items():
317
+ if user_data['user_id'] == user_id:
318
+ workspaces = user_data.get('workspaces', {})
319
+ default_workspace = workspaces.get(DEFAULT_WORKSPACE_ID, {})
320
+ chatbots = default_workspace.get('chatbots', {})
321
+ for chatbot_id, data in chatbots.items():
322
+ chatbot_name = data.get('chatbotName', 'Unnamed Agent')
323
+ agent_url = f"https://curious-learner-chatbot.web.app/#/chats?clientId={user_id}&workspaceId={DEFAULT_WORKSPACE_ID}&chatbotId={chatbot_id}"
324
+ agent_list.append(f"• {chatbot_name}\n {agent_url}")
325
+ break
326
+ return agent_list
327
+
328
+ except Exception as e:
329
+ print(f"Error fetching agents: {e}")
330
+ return []
331
+
332
+
333
+ def get_user_by_id(user_id):
334
+ """
335
+ Get user data by user ID
336
+ Returns: user data dict or None
337
+ """
338
+ try:
339
+ if FIREBASE_ENABLED:
340
+ user_doc = db.collection('g_users').document(user_id).get()
341
+ if user_doc.exists:
342
+ return user_doc.to_dict()
343
+ return None
344
+ else:
345
+ for email, data in mock_users.items():
346
+ if data['user_id'] == user_id:
347
+ return data
348
+ return None
349
+
350
+ except Exception as e:
351
+ print(f"Error fetching user: {e}")
352
+ return None
353
+
354
+
355
+ def get_user_workspace(user_id):
356
+ """
357
+ Get user's default workspace
358
+ Returns: workspace data dict or None
359
+ """
360
+ try:
361
+ if FIREBASE_ENABLED:
362
+ # Path: g_users/{user_id}/workspaces/{DEFAULT_WORKSPACE_ID}
363
+ workspace_doc = db.collection('g_users').document(user_id).collection('workspaces').document(
364
+ DEFAULT_WORKSPACE_ID).get()
365
+ if workspace_doc.exists:
366
+ return workspace_doc.to_dict()
367
+ return None
368
+ else:
369
+ for user_email, user_data in mock_users.items():
370
+ if user_data['user_id'] == user_id and 'workspaces' in user_data:
371
+ return user_data['workspaces'].get(DEFAULT_WORKSPACE_ID)
372
+ return None
373
+
374
+ except Exception as e:
375
+ print(f"Error fetching workspace: {e}")
376
+ return None
firebase-credentials.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "type": "service_account",
3
+ "project_id": "curious-learner-3845a",
4
+ "private_key_id": "eb95158f55a274b71933c84128a9a608d079ec88",
5
+ "private_key": "-----BEGIN PRIVATE KEY-----\nMIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQDLAPxtOdioHs7i\ndrac6/mfyjTX6qZ5NKVLWiJTfx+73U89YYA6oDboKwMLez1xYQilRckCcyMPdfXx\nH/UW5iKR+8U/2aCkbgy5J4Jzzprj5PEoVO+h/4pum3aDpaKeShTKbQcmnTDCHl1q\nRkUg4k5cFv3IExR/iZk5kG3Lt84dDXrH7KhJRpr1MsFjpYQ33+ngoL0G/RJ9Hyu2\nkn4KUPpegZ+QqOgpcO5YhIv0EHdV59bcCqeX6E4Dj32bPcOKBg3Z7C45Ooxhl+Ep\nvq06UgmgZ08ul0SDI5DRMgje6VPI3VrTWEEKKvWmI395Kybqbi9FZV1o40pAYiGF\n5rW84/L5AgMBAAECggEAAqoWe2fadZ5t5bVcK+QW/dISw9C4cvfOFuvtw73JO1cq\nGT/52wsg8rF50+vqqwh0gMLROBSDHcqqZIn1rAwaNmNLu/ejGaAOJQdP5C2OhTY1\n32skorIuwsk3PX7DiyNQHDYLytBzruCPe6ZvdYEy48Izfi2YmRyZDmiHCw5Js2zk\ntj5WZoMvoZunJSYiMOIT9AzqcaUmB/lPnYPCzWKa3cjN9U+3hlaagqBWUV/fLj9w\nvLTF6HwK4KxWHLQf9oSK60YoizSz7R7Dx0j8XAWTUJhPgMK75XGT4D2DRaXlk+8l\ngoiNKjGWcDO8oVeIzyozdXE7NaMWH0G4rVrofS6a7wKBgQDsLixH/aETc8ybPEdw\ns8Y4BTlXOfEXpwVMI6Xk6+4T+r8OmEdkFtWLj7QKWncege6m7T7VbmIRNiR4Gs8m\nPrRrczHwfS9P230qHty40DuJchfX/O7WyQ2D6Zmx4ixnDq1DTl9hZtmddxGPjaTD\n8VxdmPY44fkAI5/WLKGGE/8q7wKBgQDcChZLgcl/h/YSEvKJEdWwO0aDPzRz7g58\n3dx7aalPh+tRMjcazJRJxAxkt8ArZ+cJfyMjL6PkMn6US9ULUgN6rKT3Vsfi2Faq\nVFC5bzdi6gUIQsyw73dsvemJL+C4ZaXELss6yNduXomUVG95iFHFFNdQHhDnDXpw\nhy1S8zhglwKBgAxGQgrjxZFLPWD7+wKCdVTIALjly//csEvKtn51PIRRTcimZV9w\nSFzedQ7ssLAnNI38Wn2hJPucAr0zN3zXWW0UKY5EE0dlMtYTkIkSWWXFRjP1czw6\nardmVpSGGqSogJy04AQh4kFqxMDfLab5TkGXB4ThSZ2WPGJXI3XiaCqFAoGAHUD2\nD9nUeTERRPvh5NlLKJ/o0wAvMA6BPJaefoXgraMrZOMhMl3qhRgccbOASAULUVbm\nzAHEb01LSNoAG/4uWjvjvsJ51q3eb8y/4rdnjK4CN0PyRL/Bh+KDzupfnQRekoOK\nH2meQp0s+1xyaZz3ChWoPo2Qv7cqBRXjr7iIUUcCgYAVuS9+VWu49pedZ/qiUWhJ\nLRraOm5LHgkC08BdCl78XfvxrbfhhzmrDyhaiK9Qa/z705Wz9TufLmUfjk8MzdZW\nu2EqnNugcAPGPCTjuZq+cpKAN4IwxweWZyQddqnffIQTltfAhZ5gC0wCo/7moS1D\nG/rRBqYnj1gDyliDyZL25g==\n-----END PRIVATE KEY-----\n",
6
+ "client_email": "firebase-adminsdk-hg5x7@curious-learner-3845a.iam.gserviceaccount.com",
7
+ "client_id": "100249815186071791369",
8
+ "auth_uri": "https://accounts.google.com/o/oauth2/auth",
9
+ "token_uri": "https://oauth2.googleapis.com/token",
10
+ "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
11
+ "client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-hg5x7%40curious-learner-3845a.iam.gserviceaccount.com",
12
+ "universe_domain": "googleapis.com"
13
+ }
gitignore ADDED
@@ -0,0 +1,31 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
11
+
12
+ # Firebase
13
+ firebase-credentials.json
14
+
15
+ # IDE
16
+ .vscode/
17
+ .idea/
18
+ *.swp
19
+ *.swo
20
+ *~
21
+
22
+ # OS
23
+ .DS_Store
24
+ Thumbs.db
25
+
26
+ # Gradio
27
+ gradio_cached_examples/
28
+ flagged/
29
+
30
+ # Logs
31
+ *.log
gradio_app.py ADDED
@@ -0,0 +1,584 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ from datetime import datetime
3
+ import hashlib
4
+ import json
5
+
6
+ # Import database functions
7
+ from database import (
8
+ register_user as db_register_user,
9
+ login_user as db_login_user,
10
+ create_agent as db_create_agent,
11
+ get_user_agents as db_get_user_agents,
12
+ get_user_by_id,
13
+ FIREBASE_ENABLED,
14
+ DEFAULT_WORKSPACE_ID
15
+ )
16
+
17
+ # Session management
18
+ user_sessions = {}
19
+
20
+
21
+ def get_chatbot_iframe(user_id):
22
+ """Generate iframe HTML for chatbot webview"""
23
+ if not user_id:
24
+ print("[DEBUG] get_chatbot_iframe: user_id is None or empty")
25
+ return ""
26
+
27
+ chatbot_url = f"https://curious-learner-chatbot.web.app/#/chats?clientId={user_id}&workspaceId={DEFAULT_WORKSPACE_ID}"
28
+ print(f"[DEBUG] get_chatbot_iframe URL: {chatbot_url}")
29
+ return f'''
30
+ <iframe
31
+ src="{chatbot_url}"
32
+ style="width: 100%; height: 100%; border: none;"
33
+ allow="clipboard-write; clipboard-read"
34
+ ></iframe>
35
+ '''
36
+
37
+
38
+ def register_user(username, email, password, confirm_password):
39
+ """Register a new user"""
40
+ if not username or not email or not password:
41
+ return "All fields are required!", None
42
+
43
+ if password != confirm_password:
44
+ return "Passwords do not match!", None
45
+
46
+ if len(password) < 6:
47
+ return "Password must be at least 6 characters!", None
48
+
49
+ success, message, user_id = db_register_user(username, email, password)
50
+
51
+ if success:
52
+ return message + " Please login.", "login"
53
+ else:
54
+ return message, None
55
+
56
+
57
+ def login_user(email, password):
58
+ """Login user"""
59
+ if not email or not password:
60
+ return "Email and password are required!", None, None, None, None
61
+
62
+ success, message, user_id = db_login_user(email, password)
63
+
64
+ if success:
65
+ session_id = hashlib.sha256(f"{email}{datetime.now()}".encode()).hexdigest()
66
+ user_sessions[session_id] = user_id
67
+
68
+ # Create session data for cookie storage
69
+ session_data = json.dumps({
70
+ "session_id": session_id,
71
+ "user_id": user_id})
72
+
73
+ return "Login successful!", "dashboard", session_id, session_data, user_id
74
+ else:
75
+ return message, None, None, None, None
76
+
77
+
78
+ def logout_user():
79
+ """Logout user and clear session"""
80
+ return "" # Return empty string to clear cookie
81
+
82
+
83
+ def get_username(session_id):
84
+ """Get username for display"""
85
+ if not session_id or session_id not in user_sessions:
86
+ return ""
87
+
88
+ user_id = user_sessions[session_id]
89
+ user = get_user_by_id(user_id)
90
+
91
+ return user.get('name', 'User') if user else ""
92
+
93
+
94
+ def create_agent(session_id, agent_name, model_name, mcp_github_enabled, github_token, system_prompt):
95
+ """Create a new React agent"""
96
+ if not session_id or session_id not in user_sessions:
97
+ return "Please login first!", None
98
+
99
+ user_id = user_sessions[session_id]
100
+ success, message, chatbot_id = db_create_agent(
101
+ user_id, agent_name, model_name, mcp_github_enabled, github_token, system_prompt
102
+ )
103
+
104
+ return message, chatbot_id if success else None
105
+
106
+
107
+ def get_user_agents(session_id):
108
+ """Get all agents created by the user"""
109
+ if not session_id or session_id not in user_sessions:
110
+ return "Please login first!"
111
+
112
+ user_id = user_sessions[session_id]
113
+ agent_list = db_get_user_agents(user_id)
114
+
115
+ return "\n\n".join(agent_list) if agent_list else "No agents created yet."
116
+
117
+
118
+ # Custom CSS for better styling
119
+ custom_css = """
120
+ <style>
121
+ /* Desktop-friendly layout */
122
+ .gradio-container {
123
+ max-width: 1400px !important;
124
+ margin: 0 auto !important;
125
+ }
126
+
127
+ /* Larger form elements */
128
+ .contain {
129
+ max-width: 100% !important;
130
+ }
131
+
132
+ /* Auth forms centered but wider */
133
+ .auth-form {
134
+ max-width: 500px;
135
+ margin: 0 auto;
136
+ }
137
+
138
+ /* Dashboard and form containers */
139
+ .dashboard-container, .form-container {
140
+ max-width: 800px;
141
+ margin: 0 auto;
142
+ padding: 30px;
143
+ }
144
+
145
+ /* Create Agent Button - Large and prominent */
146
+ .create-agent-btn button {
147
+ font-size: 24px !important;
148
+ padding: 40px 60px !important;
149
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%) !important;
150
+ color: white !important;
151
+ border: none !important;
152
+ border-radius: 15px !important;
153
+ min-height: 120px !important;
154
+ width: 100% !important;
155
+ margin: 20px 0 !important;
156
+ }
157
+
158
+ .create-agent-btn button:hover {
159
+ transform: scale(1.02) !important;
160
+ box-shadow: 0 8px 16px rgba(0,0,0,0.2) !important;
161
+ }
162
+
163
+ /* Back button styling */
164
+ .back-btn button {
165
+ background: linear-gradient(135deg, #6B7280 0%, #4B5563 100%) !important;
166
+ color: white !important;
167
+ font-size: 16px !important;
168
+ padding: 12px 24px !important;
169
+ border-radius: 8px !important;
170
+ }
171
+
172
+ /* Logout button styling */
173
+ .logout-btn button {
174
+ background: linear-gradient(135deg, #ef4444 0%, #dc2626 100%) !important;
175
+ color: white !important;
176
+ font-size: 14px !important;
177
+ padding: 10px 20px !important;
178
+ border-radius: 8px !important;
179
+ margin-top: 30px !important;
180
+ }
181
+
182
+ .logout-btn button:hover {
183
+ background: linear-gradient(135deg, #dc2626 0%, #b91c1c 100%) !important;
184
+ }
185
+
186
+ /* MCP Config styling */
187
+ .mcp-config-box {
188
+ border: 2px solid #e5e7eb;
189
+ border-radius: 12px;
190
+ padding: 20px;
191
+ background: transparent !important;
192
+ margin: 15px 0;
193
+ }
194
+
195
+ /* Checkbox labels */
196
+ .mcp-checkbox label {
197
+ font-size: 16px !important;
198
+ font-weight: 500 !important;
199
+ }
200
+
201
+ /* Form inputs larger */
202
+ input[type="text"], input[type="email"], input[type="password"], textarea, select {
203
+ font-size: 16px !important;
204
+ padding: 12px !important;
205
+ }
206
+
207
+ /* Fix checkbox and password field backgrounds */
208
+ input[type="password"] {
209
+ background-color: var(--input-background-fill) !important;
210
+ }
211
+
212
+ input[type="checkbox"] {
213
+ background-color: transparent !important;
214
+ }
215
+
216
+ /* Buttons larger */
217
+ button {
218
+ font-size: 16px !important;
219
+ padding: 12px 24px !important;
220
+ }
221
+
222
+ /* Agent list styling */
223
+ .agent-list-container {
224
+ background: transparent !important;
225
+ border-radius: 12px;
226
+ padding: 20px;
227
+ margin-top: 20px;
228
+ }
229
+
230
+ /* Chatbot webview styling - floating chatbox */
231
+ #chatbot-webview {
232
+ position: fixed !important;
233
+ bottom: 20px !important;
234
+ right: 20px !important;
235
+ width: 380px !important;
236
+ height: 550px !important;
237
+ border: none !important;
238
+ border-radius: 16px !important;
239
+ overflow: hidden !important;
240
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.15) !important;
241
+ z-index: 9999 !important;
242
+ background: white !important;
243
+ }
244
+
245
+ #chatbot-webview iframe {
246
+ width: 100% !important;
247
+ height: 100% !important;
248
+ border: none !important;
249
+ }
250
+
251
+ /* Remove top border from first block in tabs */
252
+ .tabitem > .column > .block:first-child {
253
+ border-top: none !important;
254
+ }
255
+
256
+ /* Remove border from blocks at the top of form containers */
257
+ .form-container > .block:first-child,
258
+ .dashboard-container > .block:first-child {
259
+ border-top: none !important;
260
+ }
261
+ </style>
262
+ """
263
+
264
+ # Build the Gradio interface
265
+ with gr.Blocks(title="React Agent Builder") as app:
266
+ # Inject custom CSS
267
+ gr.HTML(custom_css)
268
+
269
+ # State variables
270
+ session_state = gr.State(None)
271
+ user_id_state = gr.State(None)
272
+
273
+ with gr.Tabs(selected="login") as tabs:
274
+ with gr.Tab("Login", id="login") as login_tab:
275
+ with gr.Column(elem_classes="auth-form"):
276
+ gr.Markdown("# 🔐 Login")
277
+ login_email = gr.Textbox(label="Email", placeholder="Enter your email", scale=1)
278
+ login_password = gr.Textbox(label="Password", type="password", placeholder="Enter your password",
279
+ scale=1)
280
+ login_btn = gr.Button("Login", variant="primary", size="lg", scale=1)
281
+ login_msg = gr.Textbox(label="Status", interactive=False, scale=1)
282
+ gr.Markdown("Don't have an account? Switch to the Registration tab.")
283
+
284
+ with gr.Tab("Register", id="register") as register_tab:
285
+ with gr.Column(elem_classes="auth-form"):
286
+ gr.Markdown("# 📝 Register")
287
+ reg_username = gr.Textbox(label="Username", placeholder="Choose a username", scale=1)
288
+ reg_email = gr.Textbox(label="Email", placeholder="Enter your email", scale=1)
289
+ reg_password = gr.Textbox(label="Password", type="password", placeholder="Choose a password", scale=1)
290
+ reg_confirm_password = gr.Textbox(label="Confirm Password", type="password",
291
+ placeholder="Confirm your password", scale=1)
292
+ reg_btn = gr.Button("Register", variant="primary", size="lg", scale=1)
293
+ reg_msg = gr.Textbox(label="Status", interactive=False, scale=1)
294
+
295
+ with gr.Tab("Dashboard", id="dashboard", visible=False) as dashboard_tab:
296
+ with gr.Column(elem_classes="dashboard-container"):
297
+ gr.Markdown("# 🚀 React Agent Dashboard")
298
+
299
+ create_agent_btn = gr.Button(
300
+ "➕ Create React Agent",
301
+ size="lg",
302
+ variant="primary",
303
+ elem_classes="create-agent-btn"
304
+ )
305
+
306
+ with gr.Column(elem_classes="agent-list-container"):
307
+ gr.Markdown("### 📋 Your Agents")
308
+ agents_list = gr.Textbox(
309
+ label="Created Agents",
310
+ interactive=False,
311
+ lines=10,
312
+ placeholder="Your created agents will appear here...",
313
+ scale=1
314
+ )
315
+ refresh_btn = gr.Button("🔄 Refresh List", size="sm")
316
+
317
+ # Logout button at the bottom of dashboard, inside the container
318
+ logout_btn_dashboard = gr.Button("🚪 Logout", size="sm", variant="secondary", elem_classes="logout-btn")
319
+
320
+ # Floating chatbot webview - outside the main container
321
+ chatbot_webview = gr.HTML(
322
+ value="",
323
+ elem_id="chatbot-webview"
324
+ )
325
+
326
+ with gr.Tab("Create Agent", id="create_agent", visible=False) as create_agent_tab:
327
+ with gr.Column(elem_classes="form-container"):
328
+ # Back button at the top
329
+ back_btn = gr.Button("← Back to Dashboard", size="lg", elem_classes="back-btn")
330
+
331
+ gr.Markdown("# 🤖 Create New React Agent")
332
+
333
+ agent_name_input = gr.Textbox(
334
+ label="Agent Name",
335
+ placeholder="Enter a name for your agent",
336
+ info="Give your agent a descriptive name",
337
+ scale=1
338
+ )
339
+
340
+ model_dropdown = gr.Dropdown(
341
+ label="Model Name",
342
+ choices=[
343
+ "gpt-4o",
344
+ "gpt-4o-mini"
345
+ ],
346
+ value="gpt-4o",
347
+ info="Select the OpenAI model to use",
348
+ scale=1
349
+ )
350
+
351
+ # MCP Server Config section
352
+ gr.Markdown("### 🔌 MCP Server Configuration")
353
+ with gr.Column(elem_classes="mcp-config-box"):
354
+ mcp_github = gr.Checkbox(
355
+ label="GitHub - Functions like commit, push, pull, update etc.",
356
+ value=False,
357
+ elem_classes="mcp-checkbox"
358
+ )
359
+
360
+ github_token_input = gr.Textbox(
361
+ label="Token",
362
+ placeholder="ghp_xxxxxxxxxxxxxxxxxxxx",
363
+ type="password",
364
+ visible=False,
365
+ scale=1
366
+ )
367
+
368
+ system_prompt_input = gr.Textbox(
369
+ label="System Context Prompt",
370
+ placeholder="Enter the system prompt for your agent...",
371
+ lines=10,
372
+ info="Define how your agent should behave and respond",
373
+ scale=1
374
+ )
375
+
376
+ submit_btn = gr.Button("✅ Submit & Create Agent", variant="primary", size="lg", scale=1)
377
+
378
+ create_msg = gr.Textbox(label="Status", interactive=False, lines=2, scale=1)
379
+ agent_url_output = gr.Textbox(label="Agent URL", interactive=False, lines=3, scale=1)
380
+
381
+ # Logout button at the bottom of create agent form
382
+ logout_btn_create = gr.Button("🚪 Logout", size="sm", variant="secondary", elem_classes="logout-btn")
383
+
384
+
385
+ # Event handlers
386
+ def handle_login(email, password):
387
+ """Handle login and return all necessary updates"""
388
+ msg, page, sess_id, cookie, user_id = login_user(email, password)
389
+
390
+ print(f"[DEBUG] handle_login: page={page}, sess_id={sess_id}, user_id={user_id}")
391
+
392
+ if page == "dashboard" and sess_id:
393
+ # Successful login - show dashboard and load agents list
394
+ # Use user_id directly to fetch agents
395
+ agent_list = db_get_user_agents(user_id)
396
+ agents_text = "\n\n".join(agent_list) if agent_list else "No agents created yet."
397
+
398
+ print(f"[DEBUG] handle_login: Generating chatbot iframe for user_id={user_id}")
399
+ chatbot_html = get_chatbot_iframe(user_id)
400
+ print(f"[DEBUG] handle_login: chatbot_html length={len(chatbot_html)}")
401
+
402
+ return {
403
+ login_msg: msg,
404
+ login_tab: gr.update(visible=False),
405
+ register_tab: gr.update(visible=False),
406
+ dashboard_tab: gr.update(visible=True),
407
+ create_agent_tab: gr.update(visible=False),
408
+ session_state: sess_id,
409
+ user_id_state: user_id,
410
+ agents_list: agents_text,
411
+ chatbot_webview: chatbot_html,
412
+ tabs: gr.update(selected="dashboard")
413
+ }
414
+ else:
415
+ # Failed login - stay on login page
416
+ return {
417
+ login_msg: msg,
418
+ login_tab: gr.update(),
419
+ register_tab: gr.update(),
420
+ dashboard_tab: gr.update(),
421
+ create_agent_tab: gr.update(),
422
+ session_state: None,
423
+ user_id_state: None,
424
+ agents_list: gr.update(),
425
+ chatbot_webview: gr.update(),
426
+ tabs: gr.update()
427
+ }
428
+
429
+
430
+ def handle_logout():
431
+ """Handle logout"""
432
+ return {
433
+ login_tab: gr.update(visible=True),
434
+ register_tab: gr.update(visible=True),
435
+ dashboard_tab: gr.update(visible=False),
436
+ create_agent_tab: gr.update(visible=False),
437
+ session_state: None,
438
+ user_id_state: None,
439
+ login_email: "",
440
+ login_password: "",
441
+ login_msg: "",
442
+ chatbot_webview: "",
443
+ tabs: gr.update(selected="login")
444
+ }
445
+
446
+
447
+ def switch_to_create_agent():
448
+ return {
449
+ dashboard_tab: gr.update(visible=False),
450
+ create_agent_tab: gr.update(visible=True),
451
+ tabs: gr.update(selected="create_agent")
452
+ }
453
+
454
+
455
+ def switch_back_to_dashboard():
456
+ return {
457
+ dashboard_tab: gr.update(visible=True),
458
+ create_agent_tab: gr.update(visible=False),
459
+ agent_name_input: "",
460
+ mcp_github: False,
461
+ github_token_input: gr.update(value="", visible=False),
462
+ system_prompt_input: "",
463
+ create_msg: "",
464
+ agent_url_output: "",
465
+ tabs: gr.update(selected="dashboard")
466
+ }
467
+
468
+
469
+ def toggle_github_token(enabled):
470
+ """Show/hide GitHub token input based on checkbox"""
471
+ return gr.update(visible=enabled)
472
+
473
+
474
+ def handle_agent_creation(sess_id, user_id, name, model, mcp_enabled, github_token, prompt):
475
+ msg, chatbot_id = create_agent(sess_id, name, model, mcp_enabled, github_token, prompt)
476
+
477
+ # Build the agent URL locally if creation was successful
478
+ agent_url = ""
479
+ if chatbot_id and user_id:
480
+ agent_url = f"https://curious-learner-chatbot.web.app/#/chats?clientId={user_id}&workspaceId={DEFAULT_WORKSPACE_ID}&chatbotId={chatbot_id}"
481
+
482
+ # Also refresh the agents list and webview after creation
483
+ agent_list = db_get_user_agents(user_id) if user_id else []
484
+ updated_agents = "\n\n".join(agent_list) if agent_list else "No agents created yet."
485
+ return {
486
+ create_msg: msg,
487
+ agent_url_output: agent_url,
488
+ agents_list: updated_agents,
489
+ chatbot_webview: get_chatbot_iframe(user_id)
490
+ }
491
+
492
+
493
+ # Refresh agents list function
494
+ def refresh_agents_list(user_id):
495
+ """Refresh agents list using user_id"""
496
+ if not user_id:
497
+ return "Please login first!"
498
+ agent_list = db_get_user_agents(user_id)
499
+ return "\n\n".join(agent_list) if agent_list else "No agents created yet."
500
+
501
+
502
+ # Login event - chain refresh after login
503
+ login_btn.click(
504
+ fn=handle_login,
505
+ inputs=[login_email, login_password],
506
+ outputs=[login_msg, login_tab, register_tab, dashboard_tab, create_agent_tab, session_state,
507
+ user_id_state, agents_list, chatbot_webview, tabs]
508
+ ).then(
509
+ fn=refresh_agents_list,
510
+ inputs=[user_id_state],
511
+ outputs=[agents_list]
512
+ )
513
+
514
+ # Logout events (both buttons do the same thing)
515
+ logout_outputs = [login_tab, register_tab, dashboard_tab, create_agent_tab, session_state,
516
+ user_id_state, login_email, login_password, login_msg, chatbot_webview, tabs]
517
+
518
+ logout_btn_dashboard.click(
519
+ fn=handle_logout,
520
+ outputs=logout_outputs
521
+ )
522
+
523
+ logout_btn_create.click(
524
+ fn=handle_logout,
525
+ outputs=logout_outputs
526
+ )
527
+
528
+ # Register event
529
+ reg_btn.click(
530
+ fn=register_user,
531
+ inputs=[reg_username, reg_email, reg_password, reg_confirm_password],
532
+ outputs=[reg_msg, gr.State()]
533
+ )
534
+
535
+ # Create agent button
536
+ create_agent_btn.click(
537
+ fn=switch_to_create_agent,
538
+ outputs=[dashboard_tab, create_agent_tab, tabs]
539
+ )
540
+
541
+ # Back button
542
+ back_btn.click(
543
+ fn=switch_back_to_dashboard,
544
+ outputs=[dashboard_tab, create_agent_tab, agent_name_input, mcp_github,
545
+ github_token_input, system_prompt_input, create_msg, agent_url_output, tabs]
546
+ )
547
+
548
+ # MCP GitHub checkbox toggle
549
+ mcp_github.change(
550
+ fn=toggle_github_token,
551
+ inputs=[mcp_github],
552
+ outputs=[github_token_input]
553
+ )
554
+
555
+ # Submit agent
556
+ submit_btn.click(
557
+ fn=handle_agent_creation,
558
+ inputs=[session_state, user_id_state, agent_name_input, model_dropdown, mcp_github,
559
+ github_token_input, system_prompt_input],
560
+ outputs=[create_msg, agent_url_output, agents_list, chatbot_webview]
561
+ )
562
+
563
+ # Refresh agents list button
564
+ refresh_btn.click(
565
+ fn=refresh_agents_list,
566
+ inputs=[user_id_state],
567
+ outputs=[agents_list]
568
+ )
569
+
570
+ if __name__ == "__main__":
571
+ app.launch(
572
+ server_name="0.0.0.0",
573
+ server_port=7860,
574
+ share=True
575
+ )
576
+
577
+
578
+ def main():
579
+ """Entry point for the application"""
580
+ app.launch(
581
+ server_name="0.0.0.0",
582
+ server_port=7860,
583
+ share=True
584
+ )
pyproject.toml ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "gradio-react-agent"
3
+ version = "0.1.0"
4
+ description = "Gradio web application with authentication and React agent creation"
5
+ readme = "README.md"
6
+ requires-python = ">=3.12"
7
+ dependencies = [
8
+ "firebase-admin>=7.1.0",
9
+ "gradio>=6.0.1",
10
+ ]
11
+
12
+ [dependency-groups]
13
+ dev = []
uv.lock ADDED
The diff for this file is too large to render. See raw diff