mgbam commited on
Commit
02e5ec9
·
verified ·
1 Parent(s): 0968321

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +98 -142
app.py CHANGED
@@ -19,20 +19,16 @@ import sys
19
  import asyncio
20
  import json
21
  import zipfile
 
22
  from pathlib import Path
23
- from typing import Dict, Any, Optional, Tuple, AsyncGenerator
 
24
  from datetime import datetime
25
 
26
  import gradio as gr
27
  import plotly.graph_objects as go
28
  import networkx as nx
29
 
30
- # Optional: upload generated ZIPs back into the Space repo
31
- try:
32
- from huggingface_hub import HfApi
33
- except Exception:
34
- HfApi = None # Safe fallback if not installed
35
-
36
  # Add project root to path
37
  sys.path.insert(0, str(Path(__file__).parent))
38
 
@@ -44,29 +40,12 @@ from ui.voice_interface import voice
44
 
45
  # Load environment variables
46
  from dotenv import load_dotenv
47
- load_dotenv()
48
 
 
49
 
50
- # =============================================================================
51
- # Helpers
52
- # =============================================================================
53
-
54
- def to_jsonable(obj: Any) -> Any:
55
- """
56
- Recursively convert objects to JSON-serializable equivalents.
57
- - Path -> str
58
- - datetime -> isoformat
59
- - dict/list/tuple/set -> recurse
60
- """
61
- if isinstance(obj, Path):
62
- return str(obj)
63
- if isinstance(obj, datetime):
64
- return obj.isoformat()
65
- if isinstance(obj, dict):
66
- return {k: to_jsonable(v) for k, v in obj.items()}
67
- if isinstance(obj, (list, tuple, set)):
68
- return [to_jsonable(v) for v in obj]
69
- return obj
70
 
71
 
72
  def create_download_zip(server_metadata: Dict[str, Any]) -> Optional[str]:
@@ -74,81 +53,80 @@ def create_download_zip(server_metadata: Dict[str, Any]) -> Optional[str]:
74
  Create a ZIP file of the generated MCP server for download.
75
 
76
  Returns:
77
- Path to the ZIP file as a string, or None if creation fails.
78
  """
79
  try:
80
  server_dir = Path(server_metadata["directory"])
81
  server_id = server_metadata["server_id"]
82
  zip_path = server_dir.parent / f"{server_id}.zip"
83
 
 
 
 
84
  with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
85
  for file_path in server_dir.rglob("*"):
86
  if file_path.is_file():
87
  arcname = file_path.relative_to(server_dir.parent)
88
  zipf.write(file_path, arcname)
89
 
90
- print(f"[OK] Created ZIP at {zip_path}")
91
  return str(zip_path)
92
  except Exception as e:
93
  print(f"[ERROR] Failed to create ZIP: {e}")
94
  return None
95
 
96
 
97
- def push_zip_to_space_repo(zip_path: str) -> Optional[str]:
98
  """
99
- Upload the generated ZIP into this Space's git repo under generated_mcps/.
100
 
101
  Uses:
102
- - SPACE_ID (provided automatically by HF for Spaces)
103
- - HF_WRITE_TOKEN (your write token, set as a secret)
104
- or HF_TOKEN as a fallback.
105
 
106
  Returns:
107
- Public Hub URL, or None if upload failed or skipped.
108
  """
109
- if not zip_path:
110
- return None
111
-
112
- space_id = os.getenv("SPACE_ID") # auto-injected in Spaces
113
- token = os.getenv("HF_WRITE_TOKEN") or os.getenv("HF_TOKEN")
114
-
115
- if HfApi is None:
116
- print("[HF] huggingface_hub not installed - skipping Hub upload.")
117
  return None
118
 
 
119
  if not space_id:
120
- print("[HF] SPACE_ID env var not found skipping Hub upload.")
121
  return None
122
 
 
123
  if not token:
124
- print("[HF] HF_WRITE_TOKEN / HF_TOKEN not set skipping Hub upload.")
125
  return None
126
 
127
- try:
128
- api = HfApi(token=token)
129
 
130
- zip_path_obj = Path(zip_path)
131
- path_in_repo = f"generated_mcps/{zip_path_obj.name}"
132
 
133
- api.upload_file(
134
- path_or_fileobj=str(zip_path_obj),
 
135
  path_in_repo=path_in_repo,
136
  repo_id=space_id,
137
  repo_type="space",
138
  )
139
-
140
- hub_url = f"https://huggingface.co/spaces/{space_id}/blob/main/{path_in_repo}"
141
- print(f"[HF] Uploaded ZIP to Hub: {hub_url}")
142
- return hub_url
143
-
144
  except Exception as e:
145
- print(f"[HF][ERROR] Failed to upload ZIP to Hub: {e}")
146
  return None
147
 
148
 
149
- # =============================================================================
150
  # Agent Visualization (Blaxel Integration)
151
- # =============================================================================
 
152
 
153
  def create_agent_graph(agent_state: Dict[str, Any]) -> go.Figure:
154
  """
@@ -195,8 +173,8 @@ def create_agent_graph(agent_state: Dict[str, Any]) -> go.Figure:
195
  node_colors = []
196
 
197
  color_map = {
198
- "planning": "#3B82F6", # Blue
199
- "generating": "#10B981", # Green
200
  "deploying": "#F59E0B", # Orange
201
  "executing": "#8B5CF6", # Purple
202
  "completed": "#6B7280", # Gray
@@ -217,11 +195,7 @@ def create_agent_graph(agent_state: Dict[str, Any]) -> go.Figure:
217
  hoverinfo="text",
218
  text=node_text,
219
  textposition="top center",
220
- marker=dict(
221
- size=30,
222
- color=node_colors,
223
- line=dict(width=2, color="white"),
224
- ),
225
  )
226
 
227
  # Create figure
@@ -242,9 +216,10 @@ def create_agent_graph(agent_state: Dict[str, Any]) -> go.Figure:
242
  return fig
243
 
244
 
245
- # =============================================================================
246
  # Core Agent Orchestration
247
- # =============================================================================
 
248
 
249
  async def orchestrate_task(
250
  user_request: str,
@@ -255,7 +230,7 @@ async def orchestrate_task(
255
  Main orchestration function - the brain of OmniMind.
256
 
257
  Yields:
258
- (status_text, agent_graph, metadata, download_zip_path)
259
  """
260
  output = "# 🤖 OmniMind Orchestrator\n\n"
261
  output += f"**Request:** {user_request}\n\n"
@@ -266,7 +241,6 @@ async def orchestrate_task(
266
  "edges": [],
267
  }
268
 
269
- # Initial state
270
  yield (output, create_agent_graph(agent_state), {}, None)
271
 
272
  # Step 1: Analyze request with multi-model router
@@ -294,7 +268,9 @@ Respond in JSON:
294
  """
295
 
296
  analysis = await router.generate(
297
- analysis_prompt, task_type=TaskType.PLANNING, temperature=0.3
 
 
298
  )
299
 
300
  try:
@@ -317,12 +293,7 @@ Respond in JSON:
317
  )
318
  agent_state["edges"].append({"from": "start", "to": "analyze"})
319
 
320
- yield (
321
- output,
322
- create_agent_graph(agent_state),
323
- to_jsonable(analysis_data),
324
- None,
325
- )
326
 
327
  # Step 2: Get knowledge context (if enabled)
328
  context = None
@@ -341,15 +312,10 @@ Respond in JSON:
341
  output += "**No relevant context found**\n\n"
342
 
343
  agent_state["nodes"][-1]["type"] = "completed"
344
- yield (
345
- output,
346
- create_agent_graph(agent_state),
347
- {"has_context": bool(context)},
348
- None,
349
- )
350
 
351
  # Step 3: Generate MCP (if needed)
352
- server_metadata: Optional[Dict[str, Any]] = None
353
  zip_path: Optional[str] = None
354
 
355
  if analysis_data.get("needs_custom_mcp", False):
@@ -370,8 +336,7 @@ Respond in JSON:
370
 
371
  output += f"✅ **Generated:** {server_metadata['server_name']}\n"
372
  output += (
373
- f"**Tools:** "
374
- f"{', '.join([t['name'] for t in server_metadata['tools']])}\n"
375
  )
376
  output += f"**Location:** `{server_metadata['directory']}`\n\n"
377
 
@@ -379,9 +344,10 @@ Respond in JSON:
379
  output += "### 📄 Generated Code Preview\n\n"
380
  output += "```python\n"
381
  try:
382
- app_file = server_metadata["files"]["app"]
383
- with open(app_file, "r", encoding="utf-8") as f:
384
- code_lines = f.readlines()[:30] # Show first 30 lines
 
385
  output += "".join(code_lines)
386
  if len(code_lines) >= 30:
387
  output += "\n... (truncated - full code saved locally)\n"
@@ -399,25 +365,22 @@ Respond in JSON:
399
  server_metadata["zip_path"] = zip_path
400
  output += "📦 **Download button updated below!**\n\n"
401
 
402
- # Try to push to Hub as well (so it appears in Files tab)
403
- hub_url = push_zip_to_space_repo(zip_path)
404
  if hub_url:
405
  server_metadata["hub_url"] = hub_url
406
- output += f"📡 **Saved to Hub:** {hub_url}\n\n"
407
  else:
408
  output += (
409
- "⚠️ Could not push ZIP to the Hub repo. "
410
- "You can still use the download button and upload manually.\n\n"
411
  )
412
- else:
413
- output += "⚠️ Failed to create ZIP archive for download.\n\n"
414
 
415
  agent_state["nodes"][-1]["type"] = "completed"
416
  yield (
417
  output,
418
  create_agent_graph(agent_state),
419
- to_jsonable(server_metadata),
420
- zip_path,
421
  )
422
 
423
  # Step 4: Deploy to Modal
@@ -426,29 +389,25 @@ Respond in JSON:
426
  {"id": "deploy", "label": "Deploy", "type": "deploying"}
427
  )
428
  agent_state["edges"].append({"from": "generate", "to": "deploy"})
429
- yield (output, create_agent_graph(agent_state), {}, zip_path)
430
 
431
  deployment = await deployer.deploy_mcp_server(server_metadata)
432
 
433
  if deployment.get("simulated"):
434
- output += "⚠️ **Simulated deployment** (configure MODAL_TOKEN for real deployment)\n"
 
 
435
 
436
  if deployment.get("status") == "failed":
437
  output += (
438
- f"⚠️ **Deployment skipped:** "
439
- f"{deployment.get('error', 'Unknown error')}\n\n"
440
  )
441
  else:
442
  output += f"**URL:** {deployment.get('modal_url', 'N/A')}\n"
443
  output += f"**Status:** {deployment.get('status', 'unknown')}\n\n"
444
 
445
  agent_state["nodes"][-1]["type"] = "completed"
446
- yield (
447
- output,
448
- create_agent_graph(agent_state),
449
- to_jsonable(deployment),
450
- zip_path,
451
- )
452
 
453
  # Step 5: Final response generation
454
  output += "## ✨ Step 5: Generating Response\n\n"
@@ -474,7 +433,9 @@ Provide a helpful response explaining what was accomplished and how the user can
474
  """
475
 
476
  final_response = await router.generate(
477
- response_prompt, task_type=TaskType.REASONING, temperature=0.7
 
 
478
  )
479
 
480
  output += final_response["response"] + "\n\n"
@@ -486,27 +447,29 @@ Provide a helpful response explaining what was accomplished and how the user can
486
  if use_voice and voice.client:
487
  output += "\n🔊 **Generating voice response...**\n"
488
  yield (output, create_agent_graph(agent_state), {}, zip_path)
489
- # Voice generation would happen here (skipped in this demo)
490
 
491
  output += "\n---\n\n"
492
  output += "**Model Usage:**\n"
493
  stats = router.get_usage_stats()
494
  output += f"- Total Requests: {stats['total_requests']}\n"
495
  output += f"- Total Cost: ${stats['total_cost']}\n"
496
- output += f"- Claude: {stats['by_model']['claude']['requests']}\n"
497
- output += f"- Gemini: {stats['by_model']['gemini']['requests']}\n"
498
- output += f"- GPT-4: {stats['by_model']['gpt4']['requests']}\n"
499
 
500
- yield (output, create_agent_graph(agent_state), to_jsonable(stats), zip_path)
501
 
502
 
503
- # =============================================================================
504
  # Gradio UI
505
- # =============================================================================
 
506
 
507
  def build_ui() -> gr.Blocks:
508
- """Build the Gradio interface"""
509
 
 
510
  custom_css = """
511
  .gradio-container {
512
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
@@ -528,7 +491,7 @@ def build_ui() -> gr.Blocks:
528
  """
529
 
530
  with gr.Blocks(title="OmniMind Orchestrator - MCP Hackathon") as app:
531
- # Inject CSS via HTML instead of css= argument (for older Gradio versions)
532
  gr.HTML(f"<style>{custom_css}</style>")
533
 
534
  gr.HTML(
@@ -536,7 +499,7 @@ def build_ui() -> gr.Blocks:
536
  <div class="main-header">
537
  <h1>🧠 OmniMind Orchestrator</h1>
538
  <p>The World's First Self-Evolving Multi-Agent MCP Ecosystem</p>
539
- <p style="font-size: 0.9em; opacity: 0.9%;">
540
  Track 2 Submission - MCP's 1st Birthday Hackathon
541
  </p>
542
  </div>
@@ -563,10 +526,7 @@ def build_ui() -> gr.Blocks:
563
 
564
  user_input = gr.Textbox(
565
  label="What do you need?",
566
- placeholder=(
567
- "Example: Create a tool that monitors my competitor's "
568
- "pricing every hour"
569
- ),
570
  lines=3,
571
  )
572
 
@@ -575,8 +535,7 @@ def build_ui() -> gr.Blocks:
575
  use_kb = gr.Checkbox(label="📚 Use Knowledge Base", value=False)
576
 
577
  submit_btn = gr.Button(
578
- "🚀 Let OmniMind Handle It",
579
- variant="primary",
580
  )
581
 
582
  gr.Markdown(
@@ -592,14 +551,12 @@ def build_ui() -> gr.Blocks:
592
 
593
  with gr.Column(scale=2):
594
  output_md = gr.Markdown(
595
- value="**Results will appear here**",
596
- label="Agent Output",
597
  )
598
 
599
  agent_graph = gr.Plot(label="🧠 Agent Brain (Real-Time)")
600
 
601
- # Use DownloadButton for file download
602
- download_btn = gr.DownloadButton(
603
  label="📦 Download Generated MCP Server",
604
  visible=False,
605
  )
@@ -667,12 +624,12 @@ def build_ui() -> gr.Blocks:
667
  1. **Never-Before-Done**: First agent that creates agents
668
  2. **All Sponsors**: Uses every sponsor technology meaningfully
669
  3. **Real Impact**: Saves enterprises weeks of custom development
670
- 4. **Beautiful UX**: Gradio + voice + visualizations
671
  5. **Production-Ready**: Clean code, error handling, scalability
672
 
673
  ### Built With
674
 
675
- - Gradio
676
  - LangGraph
677
  - Claude Sonnet 4
678
  - Gemini 2.0 Flash
@@ -694,39 +651,37 @@ def build_ui() -> gr.Blocks:
694
  async def handle_submit(request, voice_enabled, kb_enabled):
695
  """Handle user submissions"""
696
  async for (
697
- output,
698
  graph,
699
  metadata,
700
  download_zip,
701
  ) in orchestrate_task(request, voice_enabled, kb_enabled):
702
-
703
  if download_zip:
704
- # Provide a file path to DownloadButton
705
  yield (
706
- output,
707
  graph,
708
  metadata,
709
  gr.update(value=download_zip, visible=True),
710
  )
711
  else:
712
  yield (
713
- output,
714
  graph,
715
  metadata,
716
- gr.update(visible=False),
717
  )
718
 
719
  submit_btn.click(
720
  fn=handle_submit,
721
  inputs=[user_input, use_voice, use_kb],
722
- outputs=[output_md, agent_graph, metadata_json, download_btn],
723
  )
724
 
725
  gr.Markdown(
726
  """
727
  ---
728
  <div style="text-align: center; padding: 1rem; color: #666;">
729
- 🎉 Built for MCP's 1st Birthday Hackathon | Hosted by Anthropic &amp; Gradio
730
  </div>
731
  """
732
  )
@@ -734,9 +689,10 @@ def build_ui() -> gr.Blocks:
734
  return app
735
 
736
 
737
- # =============================================================================
738
  # Main Execution
739
- # =============================================================================
 
740
 
741
  if __name__ == "__main__":
742
  print("=" * 60)
 
19
  import asyncio
20
  import json
21
  import zipfile
22
+ import shutil
23
  from pathlib import Path
24
+ from typing import Dict, Any, List, Optional, Tuple, AsyncGenerator
25
+
26
  from datetime import datetime
27
 
28
  import gradio as gr
29
  import plotly.graph_objects as go
30
  import networkx as nx
31
 
 
 
 
 
 
 
32
  # Add project root to path
33
  sys.path.insert(0, str(Path(__file__).parent))
34
 
 
40
 
41
  # Load environment variables
42
  from dotenv import load_dotenv
 
43
 
44
+ load_dotenv()
45
 
46
+ # ============================================================================
47
+ # Download + Hub Upload Functionality
48
+ # ============================================================================
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
 
51
  def create_download_zip(server_metadata: Dict[str, Any]) -> Optional[str]:
 
53
  Create a ZIP file of the generated MCP server for download.
54
 
55
  Returns:
56
+ Path to the ZIP file, or None if creation fails
57
  """
58
  try:
59
  server_dir = Path(server_metadata["directory"])
60
  server_id = server_metadata["server_id"]
61
  zip_path = server_dir.parent / f"{server_id}.zip"
62
 
63
+ # Make sure parent exists
64
+ zip_path.parent.mkdir(parents=True, exist_ok=True)
65
+
66
  with zipfile.ZipFile(zip_path, "w", zipfile.ZIP_DEFLATED) as zipf:
67
  for file_path in server_dir.rglob("*"):
68
  if file_path.is_file():
69
  arcname = file_path.relative_to(server_dir.parent)
70
  zipf.write(file_path, arcname)
71
 
72
+ print(f"[ZIP] Created MCP archive at {zip_path}")
73
  return str(zip_path)
74
  except Exception as e:
75
  print(f"[ERROR] Failed to create ZIP: {e}")
76
  return None
77
 
78
 
79
+ def push_zip_to_space_repo(zip_path: Path) -> Optional[str]:
80
  """
81
+ Upload the generated ZIP into the same Space repository using HF API.
82
 
83
  Uses:
84
+ - SPACE_ID (your space id, e.g. MCP-1st-Birthday/OmniMind-Orchestrator)
85
+ - HF_WRITE_TOKEN (or HF_TOKEN) with write permission
 
86
 
87
  Returns:
88
+ A Hub URL (string) pointing to the uploaded file, or None on failure.
89
  """
90
+ try:
91
+ from huggingface_hub import HfApi
92
+ except Exception as e:
93
+ print(f"[HF] huggingface_hub not installed - skipping Space upload ({e})")
 
 
 
 
94
  return None
95
 
96
+ space_id = os.getenv("SPACE_ID")
97
  if not space_id:
98
+ print("[HF] SPACE_ID env var not set - skipping Space upload")
99
  return None
100
 
101
+ token = os.getenv("HF_WRITE_TOKEN") or os.getenv("HF_TOKEN")
102
  if not token:
103
+ print("[HF] HF_WRITE_TOKEN / HF_TOKEN not set - skipping Space upload")
104
  return None
105
 
106
+ api = HfApi(token=token)
 
107
 
108
+ # We store files under generated_mcps/ in the repo
109
+ path_in_repo = f"generated_mcps/{zip_path.name}"
110
 
111
+ try:
112
+ hub_url = api.upload_file(
113
+ path_or_fileobj=str(zip_path),
114
  path_in_repo=path_in_repo,
115
  repo_id=space_id,
116
  repo_type="space",
117
  )
118
+ # `hub_url` is already the correct URL to visualize the uploaded file
119
+ print(f"[HF] Uploaded ZIP to Hub at: {hub_url}")
120
+ return str(hub_url)
 
 
121
  except Exception as e:
122
+ print(f"[HF] Failed to upload ZIP to Hub: {e}")
123
  return None
124
 
125
 
126
+ # ============================================================================
127
  # Agent Visualization (Blaxel Integration)
128
+ # ============================================================================
129
+
130
 
131
  def create_agent_graph(agent_state: Dict[str, Any]) -> go.Figure:
132
  """
 
173
  node_colors = []
174
 
175
  color_map = {
176
+ "planning": "#3B82F6", # Blue
177
+ "generating": "#10B981", # Green
178
  "deploying": "#F59E0B", # Orange
179
  "executing": "#8B5CF6", # Purple
180
  "completed": "#6B7280", # Gray
 
195
  hoverinfo="text",
196
  text=node_text,
197
  textposition="top center",
198
+ marker=dict(size=30, color=node_colors, line=dict(width=2, color="white")),
 
 
 
 
199
  )
200
 
201
  # Create figure
 
216
  return fig
217
 
218
 
219
+ # ============================================================================
220
  # Core Agent Orchestration
221
+ # ============================================================================
222
+
223
 
224
  async def orchestrate_task(
225
  user_request: str,
 
230
  Main orchestration function - the brain of OmniMind.
231
 
232
  Yields:
233
+ (status_text, agent_graph, metadata, zip_path_for_download)
234
  """
235
  output = "# 🤖 OmniMind Orchestrator\n\n"
236
  output += f"**Request:** {user_request}\n\n"
 
241
  "edges": [],
242
  }
243
 
 
244
  yield (output, create_agent_graph(agent_state), {}, None)
245
 
246
  # Step 1: Analyze request with multi-model router
 
268
  """
269
 
270
  analysis = await router.generate(
271
+ analysis_prompt,
272
+ task_type=TaskType.PLANNING,
273
+ temperature=0.3,
274
  )
275
 
276
  try:
 
293
  )
294
  agent_state["edges"].append({"from": "start", "to": "analyze"})
295
 
296
+ yield (output, create_agent_graph(agent_state), analysis_data, None)
 
 
 
 
 
297
 
298
  # Step 2: Get knowledge context (if enabled)
299
  context = None
 
312
  output += "**No relevant context found**\n\n"
313
 
314
  agent_state["nodes"][-1]["type"] = "completed"
315
+ yield (output, create_agent_graph(agent_state), {}, None)
 
 
 
 
 
316
 
317
  # Step 3: Generate MCP (if needed)
318
+ server_metadata = None
319
  zip_path: Optional[str] = None
320
 
321
  if analysis_data.get("needs_custom_mcp", False):
 
336
 
337
  output += f"✅ **Generated:** {server_metadata['server_name']}\n"
338
  output += (
339
+ f"**Tools:** {', '.join([t['name'] for t in server_metadata['tools']])}\n"
 
340
  )
341
  output += f"**Location:** `{server_metadata['directory']}`\n\n"
342
 
 
344
  output += "### 📄 Generated Code Preview\n\n"
345
  output += "```python\n"
346
  try:
347
+ with open(
348
+ server_metadata["files"]["app"], "r", encoding="utf-8"
349
+ ) as f_code:
350
+ code_lines = f_code.readlines()[:30] # Show first 30 lines
351
  output += "".join(code_lines)
352
  if len(code_lines) >= 30:
353
  output += "\n... (truncated - full code saved locally)\n"
 
365
  server_metadata["zip_path"] = zip_path
366
  output += "📦 **Download button updated below!**\n\n"
367
 
368
+ # Upload ZIP into this same Space repo (if configured)
369
+ hub_url = push_zip_to_space_repo(Path(zip_path))
370
  if hub_url:
371
  server_metadata["hub_url"] = hub_url
372
+ output += f"🔗 **Saved to Hub:** {hub_url}\n\n"
373
  else:
374
  output += (
375
+ "⚠️ **Could not save ZIP to Hub (check Space logs / env vars).**\n\n"
 
376
  )
 
 
377
 
378
  agent_state["nodes"][-1]["type"] = "completed"
379
  yield (
380
  output,
381
  create_agent_graph(agent_state),
382
+ server_metadata,
383
+ zip_path if zip_path else None,
384
  )
385
 
386
  # Step 4: Deploy to Modal
 
389
  {"id": "deploy", "label": "Deploy", "type": "deploying"}
390
  )
391
  agent_state["edges"].append({"from": "generate", "to": "deploy"})
392
+ yield (output, create_agent_graph(agent_state), {}, None)
393
 
394
  deployment = await deployer.deploy_mcp_server(server_metadata)
395
 
396
  if deployment.get("simulated"):
397
+ output += (
398
+ "⚠️ **Simulated deployment** (configure MODAL_TOKEN for real deployment)\n"
399
+ )
400
 
401
  if deployment.get("status") == "failed":
402
  output += (
403
+ f"⚠️ **Deployment skipped:** {deployment.get('error', 'Unknown error')}\n\n"
 
404
  )
405
  else:
406
  output += f"**URL:** {deployment.get('modal_url', 'N/A')}\n"
407
  output += f"**Status:** {deployment.get('status', 'unknown')}\n\n"
408
 
409
  agent_state["nodes"][-1]["type"] = "completed"
410
+ yield (output, create_agent_graph(agent_state), deployment, zip_path)
 
 
 
 
 
411
 
412
  # Step 5: Final response generation
413
  output += "## ✨ Step 5: Generating Response\n\n"
 
433
  """
434
 
435
  final_response = await router.generate(
436
+ response_prompt,
437
+ task_type=TaskType.REASONING,
438
+ temperature=0.7,
439
  )
440
 
441
  output += final_response["response"] + "\n\n"
 
447
  if use_voice and voice.client:
448
  output += "\n🔊 **Generating voice response...**\n"
449
  yield (output, create_agent_graph(agent_state), {}, zip_path)
450
+ # (Voice generation omitted in this demo)
451
 
452
  output += "\n---\n\n"
453
  output += "**Model Usage:**\n"
454
  stats = router.get_usage_stats()
455
  output += f"- Total Requests: {stats['total_requests']}\n"
456
  output += f"- Total Cost: ${stats['total_cost']}\n"
457
+ output += f"- Claude: {stats['by_model']['claude']['requests']} requests\n"
458
+ output += f"- Gemini: {stats['by_model']['gemini']['requests']} requests\n"
459
+ output += f"- GPT-4: {stats['by_model']['gpt4']['requests']} requests\n"
460
 
461
+ yield (output, create_agent_graph(agent_state), stats, zip_path)
462
 
463
 
464
+ # ============================================================================
465
  # Gradio UI
466
+ # ============================================================================
467
+
468
 
469
  def build_ui() -> gr.Blocks:
470
+ """Build the Gradio 6 interface"""
471
 
472
+ # Custom CSS for professional look
473
  custom_css = """
474
  .gradio-container {
475
  font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
 
491
  """
492
 
493
  with gr.Blocks(title="OmniMind Orchestrator - MCP Hackathon") as app:
494
+ # Inject CSS (Blocks in this Gradio version doesn't accept css=...)
495
  gr.HTML(f"<style>{custom_css}</style>")
496
 
497
  gr.HTML(
 
499
  <div class="main-header">
500
  <h1>🧠 OmniMind Orchestrator</h1>
501
  <p>The World's First Self-Evolving Multi-Agent MCP Ecosystem</p>
502
+ <p style="font-size: 0.9em; opacity: 0.9;">
503
  Track 2 Submission - MCP's 1st Birthday Hackathon
504
  </p>
505
  </div>
 
526
 
527
  user_input = gr.Textbox(
528
  label="What do you need?",
529
+ placeholder="Example: Create a tool that monitors my competitor's pricing every hour",
 
 
 
530
  lines=3,
531
  )
532
 
 
535
  use_kb = gr.Checkbox(label="📚 Use Knowledge Base", value=False)
536
 
537
  submit_btn = gr.Button(
538
+ "🚀 Let OmniMind Handle It", variant="primary", size="lg"
 
539
  )
540
 
541
  gr.Markdown(
 
551
 
552
  with gr.Column(scale=2):
553
  output_md = gr.Markdown(
554
+ value="**Results will appear here**", label="Agent Output"
 
555
  )
556
 
557
  agent_graph = gr.Plot(label="🧠 Agent Brain (Real-Time)")
558
 
559
+ download_file = gr.File(
 
560
  label="📦 Download Generated MCP Server",
561
  visible=False,
562
  )
 
624
  1. **Never-Before-Done**: First agent that creates agents
625
  2. **All Sponsors**: Uses every sponsor technology meaningfully
626
  3. **Real Impact**: Saves enterprises weeks of custom development
627
+ 4. **Beautiful UX**: Gradio 6 + voice + visualizations
628
  5. **Production-Ready**: Clean code, error handling, scalability
629
 
630
  ### Built With
631
 
632
+ - Gradio 6.0
633
  - LangGraph
634
  - Claude Sonnet 4
635
  - Gemini 2.0 Flash
 
651
  async def handle_submit(request, voice_enabled, kb_enabled):
652
  """Handle user submissions"""
653
  async for (
654
+ out_text,
655
  graph,
656
  metadata,
657
  download_zip,
658
  ) in orchestrate_task(request, voice_enabled, kb_enabled):
 
659
  if download_zip:
 
660
  yield (
661
+ out_text,
662
  graph,
663
  metadata,
664
  gr.update(value=download_zip, visible=True),
665
  )
666
  else:
667
  yield (
668
+ out_text,
669
  graph,
670
  metadata,
671
+ gr.update(value=None, visible=False),
672
  )
673
 
674
  submit_btn.click(
675
  fn=handle_submit,
676
  inputs=[user_input, use_voice, use_kb],
677
+ outputs=[output_md, agent_graph, metadata_json, download_file],
678
  )
679
 
680
  gr.Markdown(
681
  """
682
  ---
683
  <div style="text-align: center; padding: 1rem; color: #666;">
684
+ 🎉 Built for MCP's 1st Birthday Hackathon | Hosted by Anthropic & Gradio
685
  </div>
686
  """
687
  )
 
689
  return app
690
 
691
 
692
+ # ============================================================================
693
  # Main Execution
694
+ # ============================================================================
695
+
696
 
697
  if __name__ == "__main__":
698
  print("=" * 60)