ArturoNereu commited on
Commit
220eacd
·
1 Parent(s): 2ff4c13

Cleanded up fastapi

Browse files
Files changed (2) hide show
  1. app.py +33 -61
  2. frontend/game_viewer.html +16 -10
app.py CHANGED
@@ -35,7 +35,6 @@ BASE_URL = SPACE_URL # For display in UI
35
 
36
  # Global state for current scene
37
  current_scene_id = None
38
- current_scene_url = None
39
  selected_object_id = None # Track currently looked-at object (FPS mode)
40
 
41
 
@@ -104,29 +103,38 @@ if not IS_HF_SPACES:
104
  wait_for_fastapi()
105
 
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  def create_default_scene():
108
  """Use the clean default Welcome Scene created on server startup"""
109
- global current_scene_id, current_scene_url
110
 
111
  try:
112
- # Use the pre-initialized "welcome" scene from storage
113
- # (created in backend/storage.py on module load)
114
  current_scene_id = "welcome"
115
- current_scene_url = f"{FASTAPI_URL}/view/scene/welcome"
116
-
117
- print(f"✅ Using default Welcome Scene")
118
- print(f" Scene ID: {current_scene_id}")
119
- print(f" Viewer URL: {current_scene_url}")
120
- print(f" - Clean 10x10 FPS world with physics")
121
- print(f" - Ground plane + walls (created by viewer)")
122
- print(f" - Player starts at (0, 1, 0)")
123
-
124
- return current_scene_url
125
-
126
  except Exception as e:
127
  import traceback
128
  print(f"❌ Error loading default scene: {e}")
129
- print(f" Full traceback:")
130
  traceback.print_exc()
131
  return None
132
 
@@ -145,7 +153,7 @@ def get_gpt_client():
145
 
146
  def chat_response(message, history):
147
  """Handle chat messages using GPT with tool calling"""
148
- global current_scene_id, current_scene_url
149
 
150
  # Handle help command locally (no need for LLM)
151
  if message.lower().strip() == "help":
@@ -186,9 +194,9 @@ I'm an AI assistant that can help you build 3D scenes using natural language.
186
 
187
  # Create default scene on startup
188
  print("Creating default scene...")
189
- default_viewer_url = create_default_scene()
190
- print(f"Default viewer URL: {default_viewer_url}")
191
- if not default_viewer_url:
192
  print("⚠️ WARNING: Default scene creation failed! No viewer URL generated.")
193
 
194
 
@@ -375,12 +383,12 @@ with gr.Blocks(title="GCP - Game Context Protocol") as demo:
375
 
376
  # Right column: 3D Viewer (scale=3 = ~75% width)
377
  with gr.Column(elem_id="viewer-column", scale=3):
378
- if default_viewer_url:
379
- initial_viewer_html = f'<div id="viewer-container"><iframe src="{default_viewer_url}"></iframe></div>'
380
- print(f"📊 Setting up viewer iframe with src: {default_viewer_url}")
381
  else:
382
  initial_viewer_html = '<div id="viewer-container" style="display: flex; align-items: center; justify-content: center; color: #666;"><p>⚠️ Scene failed to load. Check console logs.</p></div>'
383
- print("⚠️ No viewer URL available - showing error message")
384
 
385
  viewer = gr.HTML(
386
  value=initial_viewer_html,
@@ -506,40 +514,4 @@ with gr.Blocks(title="GCP - Game Context Protocol") as demo:
506
 
507
  if __name__ == "__main__":
508
  demo.queue()
509
-
510
- if IS_HF_SPACES:
511
- # On HF Spaces: Create a FastAPI app with our routes, then mount Gradio on it
512
- from fastapi import FastAPI, HTTPException
513
- from fastapi.responses import HTMLResponse
514
- from backend.storage import storage
515
-
516
- app = FastAPI()
517
-
518
- @app.get("/api/scenes/{scene_id}")
519
- async def get_scene_api(scene_id: str):
520
- scene = storage.get(scene_id)
521
- if not scene:
522
- raise HTTPException(status_code=404, detail=f"Scene '{scene_id}' not found")
523
- return scene
524
-
525
- @app.get("/view/scene/{scene_id}")
526
- async def view_scene(scene_id: str):
527
- scene = storage.get(scene_id)
528
- if not scene:
529
- raise HTTPException(status_code=404, detail=f"Scene '{scene_id}' not found")
530
- viewer_path = os.path.join(os.path.dirname(__file__), "frontend", "game_viewer.html")
531
- with open(viewer_path, 'r') as f:
532
- return HTMLResponse(content=f.read())
533
-
534
- @app.get("/health")
535
- async def health_check():
536
- return {"status": "healthy", "service": "GCP", "version": "2.0.0"}
537
-
538
- # Mount Gradio onto our FastAPI app
539
- app = gr.mount_gradio_app(app, demo, path="/")
540
-
541
- print("🚀 Starting on HF Spaces - FastAPI + Gradio on port 7860")
542
- uvicorn.run(app, host="0.0.0.0", port=7860)
543
- else:
544
- # Local dev: FastAPI already running on 8000 (started above), just launch Gradio on 7860
545
- demo.launch(server_name="0.0.0.0", server_port=7860)
 
35
 
36
  # Global state for current scene
37
  current_scene_id = None
 
38
  selected_object_id = None # Track currently looked-at object (FPS mode)
39
 
40
 
 
103
  wait_for_fastapi()
104
 
105
 
106
+ def get_viewer_html(scene_id="welcome"):
107
+ """Generate viewer HTML with embedded scene data."""
108
+ from backend.storage import storage
109
+
110
+ scene_data = storage.get(scene_id)
111
+ if not scene_data:
112
+ return '<div style="color: red;">Scene not found</div>'
113
+
114
+ # Read the viewer HTML template
115
+ viewer_path = os.path.join(os.path.dirname(__file__), "frontend", "game_viewer.html")
116
+ with open(viewer_path, 'r') as f:
117
+ html = f.read()
118
+
119
+ # Inject scene data before the closing </head> tag
120
+ scene_json = json.dumps(scene_data)
121
+ inject_script = f'<script>window.SCENE_DATA = {scene_json};</script>'
122
+ html = html.replace('</head>', f'{inject_script}</head>')
123
+
124
+ return html
125
+
126
+
127
  def create_default_scene():
128
  """Use the clean default Welcome Scene created on server startup"""
129
+ global current_scene_id
130
 
131
  try:
 
 
132
  current_scene_id = "welcome"
133
+ print(f"✅ Using default Welcome Scene (ID: {current_scene_id})")
134
+ return get_viewer_html(current_scene_id)
 
 
 
 
 
 
 
 
 
135
  except Exception as e:
136
  import traceback
137
  print(f"❌ Error loading default scene: {e}")
 
138
  traceback.print_exc()
139
  return None
140
 
 
153
 
154
  def chat_response(message, history):
155
  """Handle chat messages using GPT with tool calling"""
156
+ global current_scene_id
157
 
158
  # Handle help command locally (no need for LLM)
159
  if message.lower().strip() == "help":
 
194
 
195
  # Create default scene on startup
196
  print("Creating default scene...")
197
+ default_viewer_html = create_default_scene()
198
+ print(f"Default viewer HTML loaded: {len(default_viewer_html) if default_viewer_html else 0} bytes")
199
+ if not default_viewer_html:
200
  print("⚠️ WARNING: Default scene creation failed! No viewer URL generated.")
201
 
202
 
 
383
 
384
  # Right column: 3D Viewer (scale=3 = ~75% width)
385
  with gr.Column(elem_id="viewer-column", scale=3):
386
+ if default_viewer_html:
387
+ initial_viewer_html = f'<div id="viewer-container"><iframe srcdoc="{default_viewer_html.replace(chr(34), "&quot;")}" style="width:100%; height:600px; border:none;"></iframe></div>'
388
+ print(f"📊 Setting up viewer with embedded scene data")
389
  else:
390
  initial_viewer_html = '<div id="viewer-container" style="display: flex; align-items: center; justify-content: center; color: #666;"><p>⚠️ Scene failed to load. Check console logs.</p></div>'
391
+ print("⚠️ No viewer HTML available - showing error message")
392
 
393
  viewer = gr.HTML(
394
  value=initial_viewer_html,
 
514
 
515
  if __name__ == "__main__":
516
  demo.queue()
517
+ demo.launch(server_name="0.0.0.0", server_port=7860)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/game_viewer.html CHANGED
@@ -239,17 +239,23 @@
239
 
240
  async function init() {
241
  try {
242
- // Fetch scene data
243
- console.log('Fetching scene data...');
244
- const response = await fetch(`${baseUrl}/api/scenes/${sceneId}`);
245
- console.log('Response status:', response.status);
246
-
247
- if (!response.ok) {
248
- const errorText = await response.text();
249
- console.error('Failed to fetch scene:', errorText);
250
- throw new Error(`Scene not found (${response.status}): ${errorText}`);
 
 
 
 
 
 
 
251
  }
252
- sceneData = await response.json();
253
  console.log('Scene data loaded:', sceneData);
254
 
255
  // Apply player configuration from scene data
 
239
 
240
  async function init() {
241
  try {
242
+ // Check for embedded scene data first (used when served via Gradio)
243
+ if (window.SCENE_DATA) {
244
+ console.log('Using embedded scene data');
245
+ sceneData = window.SCENE_DATA;
246
+ } else {
247
+ // Fetch scene data from API (used when served via FastAPI)
248
+ console.log('Fetching scene data...');
249
+ const response = await fetch(`${baseUrl}/api/scenes/${sceneId}`);
250
+ console.log('Response status:', response.status);
251
+
252
+ if (!response.ok) {
253
+ const errorText = await response.text();
254
+ console.error('Failed to fetch scene:', errorText);
255
+ throw new Error(`Scene not found (${response.status}): ${errorText}`);
256
+ }
257
+ sceneData = await response.json();
258
  }
 
259
  console.log('Scene data loaded:', sceneData);
260
 
261
  // Apply player configuration from scene data