import os from dotenv import load_dotenv from nicegui import ui, app from langfuse import get_client from pydantic_ai.agent import Agent from components import Header, Sidebar from pages import DashboardPage, OllamaManagerPage from utils import GPUMonitor, SystemMonitor, OllamaMonitor import logging from tools import TOOLS from tools.base_tool import ToolContext, set_tool_context load_dotenv() logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logging.getLogger('watchfiles').setLevel(logging.WARNING) if all(var in os.environ for var in ['LANGFUSE_PUBLIC_KEY', 'LANGFUSE_SECRET_KEY', 'LANGFUSE_HOST']): langfuse = get_client() if langfuse.auth_check(): print("Langfuse client is authenticated and ready!") else: print("Authentication failed. Please check your credentials and host.") Agent.instrument_all() app.add_static_files('/static', 'src/static') # Create monitor instances (bindable dataclasses) system_monitor = SystemMonitor() gpu_monitor = GPUMonitor() ollama_monitor = OllamaMonitor() app.timer(2.0, system_monitor.update) app.timer(2.0, gpu_monitor.update) app.timer(2.0, ollama_monitor.update) # Initialize tool context tool_context = ToolContext( system_monitor=system_monitor, gpu_monitor=gpu_monitor, ollama_monitor=ollama_monitor ) set_tool_context(tool_context) def create_layout(current_route='/'): # Force dark mode ui.dark_mode(True) ui.query('.nicegui-content').classes('p-0 m-0') # Add custom CSS ui.add_head_html('') Header(system_monitor, gpu_monitor, ollama_monitor) Sidebar(current_route) # Create tool routes with sub-pages support for tool_baseroute, tool in TOOLS.items(): # Register all routes defined by the tool for sub_path, handler in tool.routes.items(): # Construct full route path full_route = tool.baseroute + sub_path if sub_path else tool.baseroute # Create a closure to capture the current handler and route def create_route_handler(route, handler_func): @ui.page(route) async def tool_page(): create_layout(route) await handler_func() return tool_page # Register the route create_route_handler(full_route, handler) @ui.page('/') async def index_page(): create_layout('/') DashboardPage(system_monitor, gpu_monitor, ollama_monitor) @ui.page('/ollama') async def ollama_page(): create_layout('/ollama') await OllamaManagerPage.create() # await page._load_models() @ui.page('/settings') async def settings_page(): create_layout('/settings') with ui.element('div').classes('main-content w-full'): with ui.column().classes('w-full max-w-4xl mx-auto p-6 gap-6'): ui.label('Settings').classes('text-2xl font-bold text-white') with ui.card().classes('metric-card p-6'): ui.label('Refresh Intervals').classes('text-lg font-bold text-white mb-4') with ui.column().classes('gap-4'): with ui.row().classes('items-center justify-between'): ui.label('System Stats').classes('text-white') ui.select(['1s', '2s', '5s', '10s'], value='2s').props('outlined dense color=cyan') with ui.row().classes('items-center justify-between'): ui.label('GPU Temperature').classes('text-white') ui.select(['1s', '2s', '5s', '10s'], value='5s').props('outlined dense color=cyan') with ui.card().classes('metric-card p-6 mt-4'): ui.label('About').classes('text-lg font-bold text-white mb-4') with ui.column().classes('gap-2'): with ui.row().classes('items-center gap-2'): ui.icon('computer', color='cyan') ui.label('ArchGPU Frontend v0.1.0').classes('text-white') with ui.row().classes('items-center gap-2'): ui.icon('smart_toy', color='orange') ui.label('Ollama v0.11.11').classes('text-white') if __name__ in {"__main__", "__mp_main__"}: ui.run( title=os.getenv('APP_TITLE', 'ArchGPU Frontend'), storage_secret=os.getenv('APP_STORAGE_SECRET'), port=int(os.getenv('APP_PORT', '8080')), show=os.getenv("APP_SHOW", 'false').lower() == "true", dark=True )