Nihal2000 commited on
Commit
c0c3fe0
Β·
1 Parent(s): 03caa7a

fixed agent issue

Browse files
Files changed (3) hide show
  1. app.py +161 -270
  2. calendar_integration.py +11 -11
  3. requirements.txt +4 -7
app.py CHANGED
@@ -5,11 +5,7 @@ import uvicorn
5
  import os
6
  import json
7
  from datetime import datetime
8
- from dotenv import load_dotenv
9
- from calendar_integration import create_calendar_event, initialize_calendar, get_busy_slots
10
-
11
- # Load environment variables from .env file
12
- load_dotenv()
13
 
14
  # Initialize FastAPI
15
  app = FastAPI()
@@ -24,7 +20,7 @@ async def elevenlabs_webhook(request: Request):
24
  """
25
  try:
26
  data = await request.json()
27
- print(f"πŸ“₯ Received webhook data: {json.dumps(data, indent=2)}")
28
 
29
  # ElevenLabs sends function parameters in different formats
30
  # Handle both direct parameters and nested format
@@ -41,12 +37,12 @@ async def elevenlabs_webhook(request: Request):
41
  time = params.get("time")
42
  title = params.get("title", "Meeting")
43
 
44
- print(f"πŸ“‹ Extracted: name={name}, date={date}, time={time}, title={title}")
45
 
46
  # Validate required fields
47
  if not date or not time:
48
  error_msg = "Missing required date or time information"
49
- print(f"❌ {error_msg}")
50
  return JSONResponse({
51
  "success": False,
52
  "message": error_msg
@@ -63,7 +59,7 @@ async def elevenlabs_webhook(request: Request):
63
  if event_result["success"]:
64
  # Log successful booking
65
  log_entry = {
66
- "timestamp": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
67
  "name": name,
68
  "date": date,
69
  "time": time,
@@ -71,7 +67,7 @@ async def elevenlabs_webhook(request: Request):
71
  "event_link": event_result["event_link"]
72
  }
73
  conversation_logs.append(log_entry)
74
- print(f"βœ… Event created successfully!")
75
 
76
  return JSONResponse({
77
  "success": True,
@@ -87,7 +83,7 @@ async def elevenlabs_webhook(request: Request):
87
  })
88
 
89
  except Exception as e:
90
- print(f"❌ Webhook error: {str(e)}")
91
  import traceback
92
  traceback.print_exc()
93
  return JSONResponse({
@@ -95,56 +91,15 @@ async def elevenlabs_webhook(request: Request):
95
  "message": f"An error occurred: {str(e)}"
96
  })
97
 
98
-
99
- @app.post("/webhook/check-availability")
100
- async def check_availability_webhook(request: Request):
101
- """
102
- Webhook endpoint to check calendar availability
103
- """
104
- try:
105
- data = await request.json()
106
- print(f"πŸ” Received availability check: {json.dumps(data, indent=2)}")
107
-
108
- # ElevenLabs logic to extract parameters
109
- if "parameters" in data:
110
- params = data["parameters"]
111
- elif "tool_calls" in data:
112
- params = data["tool_calls"][0]["parameters"]
113
- else:
114
- params = data
115
-
116
- date_str = params.get("date")
117
-
118
- if not date_str:
119
- return JSONResponse({
120
- "success": False,
121
- "message": "Please provide a date to check."
122
- })
123
-
124
- # Get busy slots
125
- result = get_busy_slots(date_str)
126
-
127
- return JSONResponse({
128
- "success": True,
129
- "message": result
130
- })
131
-
132
- except Exception as e:
133
- print(f"❌ Availability check error: {str(e)}")
134
- return JSONResponse({
135
- "success": False,
136
- "message": f"Error checking availability: {str(e)}"
137
- })
138
-
139
- @app.get("/api")
140
  async def root():
141
  """Health check endpoint"""
142
  return {
143
- "status": "βœ… Voice Scheduling Agent is running!",
144
  "endpoints": {
145
  "webhook": "/webhook",
146
  "logs": "/logs",
147
- "health": "/api"
148
  }
149
  }
150
 
@@ -169,221 +124,159 @@ async def health_check():
169
 
170
  # Create Gradio Interface
171
  def create_gradio_interface():
172
- """
173
- Create a "Command Center" style UI for the autonomous agent.
174
- - Top: ElevenLabs Widget for voice interaction
175
- - Bottom: Real-time Live Booking Monitor
176
- - Auto-polling for new bookings
177
- """
178
 
179
- # Get agent ID from environment
180
  agent_id = os.getenv("ELEVENLABS_AGENT_ID", "")
181
 
182
- # Define theme and css separately to avoid constructor warning in Gradio > 5.x
183
- theme = gr.themes.Soft(
184
- primary_hue="indigo",
185
- neutral_hue="slate",
186
- )
 
187
 
188
- css = """
189
- /* Modern Dark Theme Command Center */
 
 
190
  .gradio-container {
191
- background: linear-gradient(135deg, #0f172a 0%, #1e293b 100%) !important;
192
- min-height: 100vh;
193
- }
194
-
195
- /* Header styling */
196
- .header-container {
197
- text-align: center;
198
- padding: 40px 20px;
199
- background: rgba(255, 255, 255, 0.03);
200
- border-bottom: 1px solid rgba(255, 255, 255, 0.05);
201
- margin-bottom: 40px;
202
  }
203
-
204
- .app-title {
205
- color: #f8fafc;
206
- font-size: 2.5rem;
207
- font-weight: 800;
208
- background: linear-gradient(to right, #818cf8, #c084fc);
209
- -webkit-background-clip: text;
210
- -webkit-text-fill-color: transparent;
211
- margin-bottom: 10px;
212
- }
213
-
214
- .app-subtitle {
215
- color: #94a3b8;
216
- font-size: 1.1rem;
217
- font-weight: 400;
218
- }
219
-
220
- /* Widget Section */
221
- .widget-section {
222
- display: flex;
223
- justify-content: center;
224
- margin-bottom: 50px;
225
- }
226
-
227
- .widget-card {
228
- background: rgba(30, 41, 59, 0.7);
229
- border: 1px solid rgba(148, 163, 184, 0.1);
230
  border-radius: 20px;
231
- padding: 30px;
232
- width: 100%;
233
- max-width: 500px;
234
- box-shadow: 0 10px 40px -10px rgba(0, 0, 0, 0.5);
235
- backdrop-filter: blur(10px);
236
- text-align: center;
237
- }
238
-
239
- .widget-status {
240
- color: #4ade80;
241
- font-size: 0.9rem;
242
- margin-bottom: 20px;
243
- display: flex;
244
- align-items: center;
245
- justify-content: center;
246
- gap: 8px;
247
- }
248
-
249
- .pulse-dot {
250
- width: 8px;
251
- height: 8px;
252
- background-color: #4ade80;
253
- border-radius: 50%;
254
- animation: pulse 2s infinite;
255
  }
 
 
256
 
257
- @keyframes pulse {
258
- 0% { box-shadow: 0 0 0 0 rgba(74, 222, 128, 0.7); }
259
- 70% { box-shadow: 0 0 0 10px rgba(74, 222, 128, 0); }
260
- 100% { box-shadow: 0 0 0 0 rgba(74, 222, 128, 0); }
261
- }
262
-
263
- /* Logs Section */
264
- .monitor-section {
265
- max-width: 1000px;
266
- margin: 0 auto;
267
- padding: 20px;
268
- }
269
-
270
- .monitor-header {
271
- display: flex;
272
- justify-content: space-between;
273
- align-items: center;
274
- margin-bottom: 20px;
275
- color: #e2e8f0;
276
- border-bottom: 2px solid rgba(255, 255, 255, 0.1);
277
- padding-bottom: 10px;
278
- }
279
-
280
- .log-display textarea {
281
- background-color: rgba(15, 23, 42, 0.8) !important;
282
- border: 1px solid rgba(148, 163, 184, 0.2) !important;
283
- color: #60a5fa !important;
284
- font-family: 'Fira Code', 'Courier New', monospace;
285
- font-size: 0.95rem;
286
- line-height: 1.6;
287
- border-radius: 12px;
288
- }
289
 
290
- footer { visibility: hidden; }
291
- """
292
-
293
- with gr.Blocks(title="Voice Scheduling Agent") as demo:
294
- # Manually assign theme and css to avoid constructor warning
295
- demo.theme = theme
296
- demo.css = css
297
-
298
- with gr.Column(elem_classes=["header-container"]):
299
- gr.Markdown(
300
- """
301
- # πŸŽ™οΈ Voice Scheduling Agent
302
- <div class="app-subtitle">Autonomous AI Receptionist & Booking System</div>
303
- """
304
- )
305
-
306
- if agent_id:
307
- # Widget Section
308
- with gr.Row(elem_classes=["widget-section"]):
309
- gr.HTML(
310
- f"""
311
- <div class="widget-card">
312
- <div class="widget-status">
313
- <div class="pulse-dot"></div>
314
- <span>Agent is Online & Listening</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
315
  </div>
316
- <div style="font-size: 1rem; color: #cbd5e1; margin-bottom: 25px;">
317
- Click the widget below to start a conversation. <br>
318
- I will automatically extract details and book your meeting.
319
  </div>
320
- <elevenlabs-convai agent-id="{agent_id}"></elevenlabs-convai>
321
- <script src="https://elevenlabs.io/convai-widget/index.js" async type="text/javascript"></script>
322
  </div>
323
- """
324
- )
325
-
326
- # Monitor Section
327
- with gr.Column(elem_classes=["monitor-section"]):
328
- with gr.Row(elem_classes=["monitor-header"]):
329
- gr.Markdown("### πŸ“‘ Live Booking Monitor")
330
-
331
- # We'll use a TextArea to show a "Console Log" feed
332
- log_feed = gr.TextArea(
333
- label="System Activity Log",
334
- placeholder="Waiting for incoming bookings...",
335
- lines=15,
336
- max_lines=20,
337
- interactive=False,
338
- elem_classes=["log-display"]
339
- )
340
-
341
- # Stats
342
- with gr.Row():
343
- total_bookings = gr.Number(value=0, label="Total Bookings", interactive=False)
344
- last_update = gr.Textbox(value="-", label="Last Update", interactive=False)
345
-
346
- # Auto-polling mechanism
347
- timer = gr.Timer(3.0) # Check every 3 seconds
348
-
349
- def fetch_logs():
350
- try:
351
- current_count = len(conversation_logs)
352
 
353
- if current_count == 0:
354
- return "Use the widget above to make your first booking...", 0, datetime.now().strftime("%H:%M:%S")
355
-
356
- # Format logs into a readable stream
357
- log_text = ""
358
- for i, log in enumerate(reversed(conversation_logs)): # Newest first
359
- log_text += f"[{log['timestamp']}] βœ… EVENT BOOKED\n"
360
- log_text += f" Guest: {log['name']}\n"
361
- log_text += f" When: {log['date']} at {log['time']}\n"
362
- log_text += f" Title: {log['title']}\n"
363
- log_text += f" Link: {log.get('event_link', '#')}\n"
364
- log_text += "-" * 40 + "\n"
365
 
366
- return log_text, current_count, datetime.now().strftime("%H:%M:%S")
367
- except Exception as e:
368
- return f"Error fetching logs: {str(e)}", 0, datetime.now().strftime("%H:%M:%S")
369
-
370
- timer.tick(
371
- fn=fetch_logs,
372
- outputs=[log_feed, total_bookings, last_update]
373
- )
374
-
375
- else:
376
- # Fallback if ID is missing
377
- gr.Markdown(
378
- """
379
- ## ⚠️ Configuration Missing
380
-
381
- The `ELEVENLABS_AGENT_ID` environment variable is not set.
382
-
383
- Please configure it in your environment (or `.env` file) to enable the autonomous agent.
384
- """
385
- )
386
-
 
 
 
 
 
 
 
 
 
 
 
 
387
  return demo
388
 
389
 
@@ -394,29 +287,27 @@ app = gr.mount_gradio_app(app, gradio_app, path="/")
394
 
395
  if __name__ == "__main__":
396
  print("=" * 60)
397
- print("πŸš€ Starting Voice Scheduling Agent (Autonomous Mode)")
398
  print("=" * 60)
399
 
400
  # Initialize calendar service
401
- print("\nπŸ“… Initializing Google Calendar...")
402
  if initialize_calendar():
403
- print("βœ… Calendar service ready!")
404
  else:
405
- print("⚠️ Calendar service initialization failed")
406
  print("Make sure credentials.json exists or GOOGLE_CREDENTIALS_BASE64 is set")
407
 
408
  # Show configuration
409
- print("\nπŸ”§ Configuration:")
410
- print(f" Agent ID: {'βœ… Set' if os.getenv('ELEVENLABS_AGENT_ID') else '❌ Not set'}")
 
411
 
412
- # Check for credentials in all supported locations
413
- creds_found = (
414
- os.path.exists('credentials.json') or
415
- os.getenv('GOOGLE_CREDENTIALS_BASE64') or
416
- os.getenv('GOOGLE_APPLICATION_CREDENTIALS')
417
- )
418
- print(f" Google Credentials: {'βœ… Found' if creds_found else '❌ Not found'}")
419
-
420
 
421
  # Run the server
422
- uvicorn.run(app, host="127.0.0.1", port=7860)
 
5
  import os
6
  import json
7
  from datetime import datetime
8
+ from calendar_integration import create_calendar_event, initialize_calendar
 
 
 
 
9
 
10
  # Initialize FastAPI
11
  app = FastAPI()
 
20
  """
21
  try:
22
  data = await request.json()
23
+ print(f"Received webhook data: {json.dumps(data, indent=2)}")
24
 
25
  # ElevenLabs sends function parameters in different formats
26
  # Handle both direct parameters and nested format
 
37
  time = params.get("time")
38
  title = params.get("title", "Meeting")
39
 
40
+ print(f"Extracted: name={name}, date={date}, time={time}, title={title}")
41
 
42
  # Validate required fields
43
  if not date or not time:
44
  error_msg = "Missing required date or time information"
45
+ print(f"{error_msg}")
46
  return JSONResponse({
47
  "success": False,
48
  "message": error_msg
 
59
  if event_result["success"]:
60
  # Log successful booking
61
  log_entry = {
62
+ "timestamp": datetime.now().isoformat(),
63
  "name": name,
64
  "date": date,
65
  "time": time,
 
67
  "event_link": event_result["event_link"]
68
  }
69
  conversation_logs.append(log_entry)
70
+ print(f"Event created successfully!")
71
 
72
  return JSONResponse({
73
  "success": True,
 
83
  })
84
 
85
  except Exception as e:
86
+ print(f"Webhook error: {str(e)}")
87
  import traceback
88
  traceback.print_exc()
89
  return JSONResponse({
 
91
  "message": f"An error occurred: {str(e)}"
92
  })
93
 
94
+ @app.get("/")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
95
  async def root():
96
  """Health check endpoint"""
97
  return {
98
+ "status": "Voice Scheduling Agent is running!",
99
  "endpoints": {
100
  "webhook": "/webhook",
101
  "logs": "/logs",
102
+ "health": "/"
103
  }
104
  }
105
 
 
124
 
125
  # Create Gradio Interface
126
  def create_gradio_interface():
127
+ """Create the Gradio UI with embedded ElevenLabs widget"""
 
 
 
 
 
128
 
129
+ # Get agent ID from environment (HuggingFace Secrets)
130
  agent_id = os.getenv("ELEVENLABS_AGENT_ID", "")
131
 
132
+ # Get the Space URL dynamically
133
+ space_name = os.getenv("SPACE_ID", "")
134
+ if space_name:
135
+ webhook_url = f"https://{space_name}.hf.space/webhook"
136
+ else:
137
+ webhook_url = "https://YOUR_SPACE_URL/webhook"
138
 
139
+ with gr.Blocks(
140
+ theme=gr.themes.Soft(primary_hue="blue", secondary_hue="purple"),
141
+ title="πŸŽ™οΈ Voice Scheduling Agent",
142
+ css="""
143
  .gradio-container {
144
+ max-width: 1200px !important;
 
 
 
 
 
 
 
 
 
 
145
  }
146
+ .widget-container {
147
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
148
  border-radius: 20px;
149
+ padding: 40px;
150
+ box-shadow: 0 10px 30px rgba(0,0,0,0.2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
151
  }
152
+ """
153
+ ) as demo:
154
 
155
+ gr.Markdown("""
156
+ # πŸŽ™οΈ Voice Scheduling Agent
157
+ ### Schedule meetings using natural voice conversation with AI
158
+ """)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
159
 
160
+ with gr.Row():
161
+ # Left column - Instructions
162
+ with gr.Column(scale=1):
163
+ gr.Markdown("""
164
+ ## πŸ“ How to Use
165
+
166
+ 1. **Click the microphone** button on the right
167
+ 2. **Speak naturally** - just talk to the AI!
168
+ 3. **Provide details** when asked:
169
+ - Your name
170
+ - Meeting date
171
+ - Meeting time
172
+ - Meeting title (optional)
173
+ 4. **Confirm** when the AI repeats your details
174
+ 5. **Done!** Your event is created automatically
175
+
176
+ ### πŸ“… Date Format Examples:
177
+ - "December 25, 2024"
178
+ - "25th December 2024"
179
+ - "2024-12-25"
180
+
181
+ ### πŸ• Time Format Examples:
182
+ - "2:30 PM"
183
+ - "14:30"
184
+ - "two thirty in the afternoon"
185
+
186
+ ### πŸ’‘ Tips:
187
+ - Speak clearly and naturally
188
+ - Wait for the AI to finish before responding
189
+ - You can interrupt if needed
190
+ - Say "yes" or "correct" to confirm details
191
+ """)
192
+
193
+ # Show webhook URL and status
194
+ gr.Markdown(f"""
195
+ ---
196
+ ### πŸ”§ Configuration
197
+ **Webhook URL:** `{webhook_url}`
198
+
199
+ **Status:** {"βœ… Configured" if agent_id else "⚠️ Agent ID not set"}
200
+ """)
201
+
202
+ # Recent bookings section
203
+ gr.Markdown("### πŸ“Š Recent Bookings")
204
+ logs_display = gr.JSON(label="Latest Events", value=[])
205
+
206
+ def get_recent_logs():
207
+ """Get the 5 most recent bookings"""
208
+ recent = conversation_logs[-5:] if conversation_logs else []
209
+ return recent[::-1] # Reverse to show newest first
210
+
211
+ refresh_btn = gr.Button("πŸ”„ Refresh Bookings", size="sm")
212
+ refresh_btn.click(get_recent_logs, outputs=logs_display)
213
+
214
+ # Right column - Voice Widget
215
+ with gr.Column(scale=1):
216
+ if agent_id:
217
+ gr.HTML(f"""
218
+ <div class="widget-container">
219
+ <div style="text-align: center; margin-bottom: 20px;">
220
+ <h2 style="color: white; margin: 0;">🎀 Voice Assistant</h2>
221
+ <p style="color: rgba(255,255,255,0.9); margin-top: 10px;">
222
+ Click the button below to start talking
223
+ </p>
224
+ </div>
225
+
226
+ <div id="elevenlabs-widget" style="display: flex; justify-content: center;">
227
+ <script src="https://elevenlabs.io/convai-widget/index.js" async type="text/javascript"></script>
228
+ <elevenlabs-convai agent-id="{agent_id}"></elevenlabs-convai>
229
  </div>
230
+
231
+ <div style="text-align: center; margin-top: 20px; color: white; font-size: 14px;">
232
+ <p>πŸ”Š Make sure your microphone is enabled</p>
233
  </div>
 
 
234
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
 
236
+ <style>
237
+ elevenlabs-convai {{
238
+ width: 100% !important;
239
+ max-width: 400px;
240
+ }}
241
+ </style>
242
+ """)
243
+ else:
244
+ gr.Markdown("""
245
+ ### ⚠️ Configuration Required
 
 
246
 
247
+ Please add your ElevenLabs Agent ID to the HuggingFace Space secrets:
248
+
249
+ 1. Go to Space Settings
250
+ 2. Navigate to "Repository secrets"
251
+ 3. Add `ELEVENLABS_AGENT_ID` with your agent ID
252
+ 4. Restart the Space
253
+
254
+ **Note:** Make sure to also configure the webhook URL in your ElevenLabs agent settings.
255
+ """)
256
+
257
+ # Footer
258
+ gr.Markdown("""
259
+ ---
260
+ ### πŸ› οΈ Tech Stack
261
+ - **Voice AI:** ElevenLabs Conversational AI
262
+ - **Calendar:** Google Calendar API
263
+ - **Backend:** FastAPI + Python
264
+ - **Frontend:** Gradio
265
+ - **Deployment:** HuggingFace Spaces
266
+
267
+ ### πŸ“ Setup Instructions
268
+
269
+ **Required Secrets (Add in Space Settings):**
270
+ - `ELEVENLABS_AGENT_ID` - Your ElevenLabs agent ID
271
+ - `ELEVENLABS_API_KEY` - Your ElevenLabs API key (optional)
272
+ - `GOOGLE_CREDENTIALS_BASE64` - Your Google service account credentials (base64 encoded)
273
+
274
+ **Or upload `credentials.json` directly to the Space**
275
+
276
+ ---
277
+ Built for Vikara.ai Assessment | [View on GitHub](#)
278
+ """)
279
+
280
  return demo
281
 
282
 
 
287
 
288
  if __name__ == "__main__":
289
  print("=" * 60)
290
+ print("Starting Voice Scheduling Agent")
291
  print("=" * 60)
292
 
293
  # Initialize calendar service
294
+ print("\nInitializing Google Calendar...")
295
  if initialize_calendar():
296
+ print("Calendar service ready!")
297
  else:
298
+ print("Calendar service initialization failed")
299
  print("Make sure credentials.json exists or GOOGLE_CREDENTIALS_BASE64 is set")
300
 
301
  # Show configuration
302
+ print("\nConfiguration:")
303
+ print(f" Agent ID: {'Set' if os.getenv('ELEVENLABS_AGENT_ID') else 'Not set'}")
304
+ print(f" Google Credentials: {'Found' if os.path.exists('credentials.json') or os.getenv('GOOGLE_CREDENTIALS_BASE64') else 'Not found'}")
305
 
306
+ print("\n" + "=" * 60)
307
+ print("Server starting...")
308
+ print(" Local: http://localhost:7860")
309
+ print(" Webhook: http://localhost:7860/webhook")
310
+ print("=" * 60 + "\n")
 
 
 
311
 
312
  # Run the server
313
+ uvicorn.run(app, host="0.0.0.0", port=7860)
calendar_integration.py CHANGED
@@ -35,7 +35,7 @@ def get_credentials():
35
 
36
  # 1. Try local file
37
  if os.path.exists(SERVICE_ACCOUNT_FILE):
38
- print(f"πŸ“„ Loading credentials from {SERVICE_ACCOUNT_FILE}")
39
  return service_account.Credentials.from_service_account_file(
40
  SERVICE_ACCOUNT_FILE, scopes=SCOPES
41
  )
@@ -51,7 +51,7 @@ def get_credentials():
51
  if not content:
52
  continue
53
 
54
- print(f"πŸ” Checking {var_name}...")
55
 
56
  # A. Check if it's a raw JSON string
57
  if content.strip().startswith('{'):
@@ -70,7 +70,7 @@ def get_credentials():
70
  content, scopes=SCOPES
71
  )
72
  except Exception as e:
73
- print(f" ❌ Error loading file from {var_name}: {e}")
74
 
75
  # C. Try Base64 decode
76
  else:
@@ -84,11 +84,11 @@ def get_credentials():
84
  creds_dict = json.loads(decoded)
85
  return load_from_dict(creds_dict)
86
  else:
87
- print(" ⚠️ Decoded content is not JSON (skipping)")
88
  except Exception as e:
89
- print(f" ❌ Failed to process as Base64/Path/JSON: {e}")
90
 
91
- print("❌ No valid credentials found in files or environment variables!")
92
  return None
93
 
94
 
@@ -104,11 +104,11 @@ def initialize_calendar():
104
 
105
  # Build the calendar service
106
  calendar_service = build('calendar', 'v3', credentials=credentials)
107
- print("βœ… Google Calendar service initialized successfully!")
108
  return calendar_service
109
 
110
  except Exception as e:
111
- print(f"❌ Error initializing calendar service: {str(e)}")
112
  import traceback
113
  traceback.print_exc()
114
  return None
@@ -276,7 +276,7 @@ def create_calendar_event(name, date, time, title="Meeting", duration_hours=1):
276
  },
277
  }
278
 
279
- print(f"πŸ“€ Sending event to Google Calendar...")
280
 
281
  # Insert the event
282
  created_event = calendar_service.events().insert(
@@ -287,7 +287,7 @@ def create_calendar_event(name, date, time, title="Meeting", duration_hours=1):
287
  event_link = created_event.get('htmlLink')
288
  event_id = created_event.get('id')
289
 
290
- print(f"βœ… Event created successfully!")
291
  print(f" Event ID: {event_id}")
292
  print(f" Link: {event_link}")
293
 
@@ -300,7 +300,7 @@ def create_calendar_event(name, date, time, title="Meeting", duration_hours=1):
300
 
301
  except Exception as e:
302
  error_msg = f"Failed to create calendar event: {str(e)}"
303
- print(f"❌ {error_msg}")
304
  import traceback
305
  traceback.print_exc()
306
  return {
 
35
 
36
  # 1. Try local file
37
  if os.path.exists(SERVICE_ACCOUNT_FILE):
38
+ print(f"Loading credentials from {SERVICE_ACCOUNT_FILE}")
39
  return service_account.Credentials.from_service_account_file(
40
  SERVICE_ACCOUNT_FILE, scopes=SCOPES
41
  )
 
51
  if not content:
52
  continue
53
 
54
+ print(f"Checking {var_name}...")
55
 
56
  # A. Check if it's a raw JSON string
57
  if content.strip().startswith('{'):
 
70
  content, scopes=SCOPES
71
  )
72
  except Exception as e:
73
+ print(f" Error loading file from {var_name}: {e}")
74
 
75
  # C. Try Base64 decode
76
  else:
 
84
  creds_dict = json.loads(decoded)
85
  return load_from_dict(creds_dict)
86
  else:
87
+ print(" Decoded content is not JSON (skipping)")
88
  except Exception as e:
89
+ print(f" Failed to process as Base64/Path/JSON: {e}")
90
 
91
+ print("No valid credentials found in files or environment variables!")
92
  return None
93
 
94
 
 
104
 
105
  # Build the calendar service
106
  calendar_service = build('calendar', 'v3', credentials=credentials)
107
+ print("Google Calendar service initialized successfully!")
108
  return calendar_service
109
 
110
  except Exception as e:
111
+ print(f"Error initializing calendar service: {str(e)}")
112
  import traceback
113
  traceback.print_exc()
114
  return None
 
276
  },
277
  }
278
 
279
+ print(f"Sending event to Google Calendar...")
280
 
281
  # Insert the event
282
  created_event = calendar_service.events().insert(
 
287
  event_link = created_event.get('htmlLink')
288
  event_id = created_event.get('id')
289
 
290
+ print(f"Event created successfully!")
291
  print(f" Event ID: {event_id}")
292
  print(f" Link: {event_link}")
293
 
 
300
 
301
  except Exception as e:
302
  error_msg = f"Failed to create calendar event: {str(e)}"
303
+ print(f" {error_msg}")
304
  import traceback
305
  traceback.print_exc()
306
  return {
requirements.txt CHANGED
@@ -1,9 +1,6 @@
1
- gradio>=5.9.0
2
  fastapi>=0.109.0
3
- uvicorn>=0.27.0
4
  google-auth>=2.27.0
5
- google-auth-oauthlib>=1.2.0
6
- google-auth-httplib2>=0.2.0
7
- google-api-python-client>=2.118.0
8
- python-multipart>=0.0.6
9
- python-dotenv>=1.0.0
 
1
+ gradio>=4.44.0
2
  fastapi>=0.109.0
3
+ uvicorn[standard]>=0.27.0
4
  google-auth>=2.27.0
5
+ google-api-python-client>=2.116.0
6
+ python-multipart>=0.0.6