1616from datetime import datetime
1717from pathlib import Path
1818from typing import List , Optional
19+ import urllib .request
1920
2021from fastapi import (
2122 FastAPI ,
@@ -109,9 +110,29 @@ def health_check():
109110 return {"status" : "ok" }
110111
111112
113+ def ensure_assets ():
114+ """Download tutorial assets if they are missing."""
115+ base_url = (
116+ "https://raw.githubusercontent.com/TemoaProject/temoa-web-gui/main/assets/"
117+ )
118+ assets_dir = Path ("assets" )
119+ assets_dir .mkdir (exist_ok = True )
120+
121+ files = ["tutorial_database.sqlite" , "tutorial_config.toml" ]
122+ for f in files :
123+ target = assets_dir / f
124+ if not target .exists ():
125+ print (f"Downloading missing asset: { f } ..." )
126+ try :
127+ urllib .request .urlretrieve (base_url + f , target )
128+ except Exception as e :
129+ print (f"Failed to download { f } : { e } " )
130+
131+
112132@app .get ("/api/config" )
113133def get_config ():
114134 """Return key configuration paths and settings for the frontend."""
135+ ensure_assets ()
115136 # In the runner, we assume assets are in the current directory or nearby
116137 tutorial_db = Path ("assets/tutorial_database.sqlite" )
117138 return {
@@ -361,13 +382,27 @@ async def websocket_endpoint(websocket: WebSocket):
361382 import uvicorn
362383 import subprocess
363384
385+ ensure_assets ()
386+
364387 # Start Datasette in a subprocess
365- print ("Starting Datasette on port 8001..." )
388+ print ("Starting Datasette on port 8001..." , flush = True )
366389 try :
390+ log_file = open ("datasette.log" , "a" )
391+ # Prepare list of things to serve: output directory and tutorial db
392+ to_serve = [str (Path ("output" ).absolute ())]
393+ tutorial_db = Path ("assets/tutorial_database.sqlite" )
394+ if tutorial_db .exists ():
395+ to_serve .append (str (tutorial_db .absolute ()))
396+
397+ # Use sys.executable -m datasette to ensure we run in the same environment
398+ # Only serve the results and tutorial data, NOT the whole root (prevents config.json errors)
367399 subprocess .Popen (
368400 [
401+ sys .executable ,
402+ "-m" ,
369403 "datasette" ,
370- "." ,
404+ "serve" ,
405+ * to_serve ,
371406 "--port" ,
372407 "8001" ,
373408 "--host" ,
@@ -376,10 +411,13 @@ async def websocket_endpoint(websocket: WebSocket):
376411 "sql_time_limit_ms" ,
377412 "5000" ,
378413 ],
379- stdout = subprocess .DEVNULL ,
380- stderr = subprocess .DEVNULL ,
414+ stdout = log_file ,
415+ stderr = log_file ,
416+ )
417+ print (
418+ "Datasette process launched. (Logs available in datasette.log)" , flush = True
381419 )
382420 except Exception as e :
383- print (f"Warning: Could not start Datasette: { e } " )
421+ print (f"Warning: Could not start Datasette: { e } " , flush = True )
384422
385423 uvicorn .run (app , host = "0.0.0.0" , port = 8000 )
0 commit comments