Skip to content

Commit 79ce036

Browse files
author
Dylan Huang
committed
add --port arg to ep logs
1 parent 38a4444 commit 79ce036

File tree

15 files changed

+334
-113
lines changed

15 files changed

+334
-113
lines changed

eval_protocol/cli.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,7 @@ def parse_args(args=None):
289289

290290
# Logs command
291291
logs_parser = subparsers.add_parser("logs", help="Serve logs with file watching and real-time updates")
292+
logs_parser.add_argument("--port", type=int, default=8000, help="Port to bind to (default: 8000)")
292293

293294
# Run command (for Hydra-based evaluations)
294295
# This subparser intentionally defines no arguments itself.

eval_protocol/cli_commands/logs.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@
1111
def logs_command(args):
1212
"""Serve logs with file watching and real-time updates"""
1313

14+
port = args.port
1415
print(f"🚀 Starting Eval Protocol Logs Server")
15-
print(f"🌐 URL: http://localhost:8000")
16-
print(f"🔌 WebSocket: ws://localhost:8000/ws")
16+
print(f"🌐 URL: http://localhost:{port}")
17+
print(f"🔌 WebSocket: ws://localhost:{port}/ws")
1718
print(f"👀 Watching paths: {['current directory']}")
1819
print("Press Ctrl+C to stop the server")
1920
print("-" * 50)
2021

2122
try:
22-
serve_logs()
23+
serve_logs(port=args.port)
2324
return 0
2425
except KeyboardInterrupt:
2526
print("\n🛑 Server stopped by user")

eval_protocol/utils/logs_server.py

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -319,20 +319,52 @@ def run(self):
319319
asyncio.run(self.run_async())
320320

321321

322-
server = LogsServer()
323-
app = server.app
322+
def create_app(host: str = "localhost", port: int = 8000, build_dir: Optional[str] = None) -> FastAPI:
323+
"""
324+
Factory function to create a FastAPI app instance.
325+
326+
This allows uvicorn to call it with parameters and avoids top-level variable instantiation.
327+
328+
Args:
329+
host: Host to bind to
330+
port: Port to bind to
331+
build_dir: Optional custom build directory path
332+
333+
Returns:
334+
FastAPI app instance
335+
"""
336+
if build_dir is None:
337+
build_dir = os.path.abspath(
338+
os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), "vite-app", "dist")
339+
)
324340

341+
server = LogsServer(host=host, port=port, build_dir=build_dir)
342+
return server.app
325343

326-
def serve_logs():
344+
345+
# For backward compatibility and direct usage
346+
def serve_logs(port: Optional[int] = None):
327347
"""
328348
Convenience function to create and run a LogsServer.
329349
"""
330-
global server, app
331-
if server is None:
332-
server = LogsServer()
333-
app = server.app
350+
server = LogsServer(port=port)
334351
server.run()
335352

336353

337354
if __name__ == "__main__":
338-
serve_logs()
355+
import argparse
356+
357+
parser = argparse.ArgumentParser(description="Start the evaluation logs server")
358+
parser.add_argument("--host", default="localhost", help="Host to bind to (default: localhost)")
359+
parser.add_argument("--port", type=int, default=8000, help="Port to bind to (default: 8000)")
360+
parser.add_argument("--build-dir", help="Path to Vite build directory")
361+
362+
args = parser.parse_args()
363+
364+
# Create server with command line arguments
365+
if args.build_dir:
366+
server = LogsServer(host=args.host, port=args.port, build_dir=args.build_dir)
367+
else:
368+
server = LogsServer(host=args.host, port=args.port)
369+
370+
server.run()

eval_protocol/utils/vite_server.py

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import uvicorn
77
from fastapi import FastAPI, HTTPException
8-
from fastapi.responses import FileResponse
8+
from fastapi.responses import FileResponse, HTMLResponse
99
from fastapi.staticfiles import StaticFiles
1010

1111
logger = logging.getLogger(__name__)
@@ -57,6 +57,40 @@ def __init__(
5757
# Setup routes
5858
self._setup_routes()
5959

60+
def _inject_config_into_html(self, html_content: str) -> str:
61+
"""Inject server configuration into the HTML content."""
62+
config_script = f"""
63+
<script>
64+
// Server-injected configuration
65+
window.SERVER_CONFIG = {{
66+
host: "{self.host}",
67+
port: "{self.port}",
68+
protocol: "ws",
69+
apiProtocol: "http"
70+
}};
71+
</script>
72+
"""
73+
74+
# Insert the config script before the closing </head> tag
75+
if "</head>" in html_content:
76+
return html_content.replace("</head>", f"{config_script}</head>")
77+
else:
78+
# If no </head> tag, insert at the beginning
79+
return f"{config_script}{html_content}"
80+
81+
def _serve_index_with_config(self) -> HTMLResponse:
82+
"""Serve the index.html file with injected configuration."""
83+
index_path = self.build_dir / self.index_file
84+
if index_path.exists():
85+
with open(index_path, "r", encoding="utf-8") as f:
86+
html_content = f.read()
87+
88+
# Inject server configuration
89+
enhanced_html = self._inject_config_into_html(html_content)
90+
return HTMLResponse(content=enhanced_html)
91+
92+
raise HTTPException(status_code=404, detail="Index file not found")
93+
6094
def _setup_routes(self):
6195
"""Set up the API routes for serving the SPA."""
6296

@@ -81,18 +115,15 @@ async def serve_spa(path: str):
81115
# For SPA routing, serve index.html for non-existent routes
82116
# but exclude API routes and asset requests
83117
if not path.startswith(("api/", "assets/")):
84-
index_path = self.build_dir / self.index_file
85-
if index_path.exists():
86-
return FileResponse(index_path)
118+
return self._serve_index_with_config()
87119

88120
# If we get here, the file doesn't exist and it's not a SPA route
89121
raise HTTPException(status_code=404, detail="File not found")
90122

91123
@self.app.get("/")
92124
async def root():
93-
"""Serve the main index.html file."""
94-
index_path = self.build_dir / self.index_file
95-
return FileResponse(index_path)
125+
"""Serve the main index.html file with injected configuration."""
126+
return self._serve_index_with_config()
96127

97128
@self.app.get("/health")
98129
async def health():

vite-app/dist/assets/index-CGYj40Gx.css

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vite-app/dist/assets/index-DWfIf2rx.css

Lines changed: 0 additions & 1 deletion
This file was deleted.

vite-app/dist/assets/index-D_nkLTVA.js

Lines changed: 0 additions & 88 deletions
This file was deleted.

vite-app/dist/assets/index-D_nkLTVA.js.map

Lines changed: 0 additions & 1 deletion
This file was deleted.

vite-app/dist/assets/index-t_hsfGP1.js

Lines changed: 88 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

vite-app/dist/assets/index-t_hsfGP1.js.map

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)