diff --git a/apps/api/src/services/terminal_manager.py b/apps/api/src/services/terminal_manager.py index 70010dc..c48c341 100644 --- a/apps/api/src/services/terminal_manager.py +++ b/apps/api/src/services/terminal_manager.py @@ -23,8 +23,14 @@ class TerminalManager: def _start_idle_check(self) -> None: """Start the idle timeout background task.""" - if self._idle_check_task is None or self._idle_check_task.done(): - self._idle_check_task = asyncio.create_task(self._idle_check_loop()) + if self._idle_check_task is not None and not self._idle_check_task.done(): + return + try: + loop = asyncio.get_running_loop() + self._idle_check_task = loop.create_task(self._idle_check_loop()) + except RuntimeError: + # No event loop running yet, will be started lazily + pass async def _idle_check_loop(self) -> None: """Periodically check for idle sessions and clean them up.""" @@ -54,6 +60,9 @@ class TerminalManager: container_id: str, ) -> TerminalSession: """Get existing session or create a new one.""" + # Ensure idle check is running (lazy start) + self._start_idle_check() + instance_id_str = str(instance_id) # Check for existing session diff --git a/apps/web/src/components/terminal.tsx b/apps/web/src/components/terminal.tsx index 2bf0850..9c23d67 100644 --- a/apps/web/src/components/terminal.tsx +++ b/apps/web/src/components/terminal.tsx @@ -201,7 +201,15 @@ export const TerminalComponent: React.FC = ({ term.loadAddon(fitAddon); term.loadAddon(new WebLinksAddon()); - term.open(terminalRef.current); + // Ensure container has explicit dimensions before xterm initializes + const container = terminalRef.current; + const parentRect = container.parentElement?.getBoundingClientRect(); + if (parentRect) { + container.style.width = `${parentRect.width}px`; + container.style.height = `${parentRect.height}px`; + } + + term.open(container); // Connect WebSocket const ws = connectWebSocket();