Commit Graph

63 Commits

Author SHA1 Message Date
alex 22474cdba5 style: fix all ruff and eslint errors across codebase
Backend (ruff):
- Fix 106 errors: move imports to top of file (E402)
- Remove unused imports (F401)
- Add missing imports for undefined names (F821)
- Remove unused variables (F841)
- Fix test_models.py broken RefreshToken test
- Fix test_projects_api.py missing TestClient import

Frontend (eslint):
- Remove unused imports/variables across 10 files
- Fix explicit any types in client.ts and sessions.ts
- Clean up empty block statements in terminal.tsx

Quality gates: ruff (pass), eslint (pass), tsc --noEmit (pass),
pytest (98 passed, 4 pre-existing failures)
2026-05-28 10:15:59 +02:00
alex 0c839e8c6f fix: terminal 4004 infinite reconnect loop for pi-agent tool type
- Add stdin_open: true and tty: true to dockerfile-based compose generation.
  Without these, bash (PID 1) exits immediately, causing a container restart
  loop that makes the instance invisible to docker ps and triggers 4004.
- Treat WebSocket close codes 4001/4003/4004 as permanent errors in the
  frontend. Stop retrying and show the server reason to the user.
- Prevent visibilitychange handler from resetting retry attempts after a
  permanent error has occurred.
- Use docker ps -a in get_container_id/get_container_name to find
  stopped/exited containers for diagnostics.

Quality gates: tsc --noEmit (pass), pytest (98 passed, 4 pre-existing failures)
2026-05-28 09:33:35 +02:00
Alex Blank d6ea5fb1fd chore: clean up debugging logs and console prints
Frontend:
- Remove 18 console.log/warn/error statements from terminal.tsx
- Remove console.warn from icon.tsx

Backend:
- Downgrade routine logger.info to logger.debug in tool_instances.py, terminal.py,
  terminal_session.py, terminal_manager.py, auth.py, docker_build.py, clone.py,
  config_profiles.py, user_config.py
- Keep important lifecycle events as logger.info:
  * Instance creation, start, running state
  * Docker build success/failure
  * Terminal session creation and reset
  * Auth success and user creation
  * Readiness probe success
  * Tunnel creation/stop
2026-05-27 22:16:59 +02:00
Alex Blank adda76a2ff fix: remove viewport-based font size calculation causing jump on mobile
The calculateFontSize() function was overriding the font size on mobile
based on viewport width (vw/25), causing the terminal to display at ~15px
while the internal state was 8px. When pressing A-, it would jump from
15px to 7px. Now it respects the actual fontSize state consistently.

Quality gates: TypeScript check passed, production build successful
2026-05-26 21:19:47 +02:00
Alex Blank 47962ed476 fix: set terminal default to 8px and minimum to 4px
- Reduce MIN_FONT_SIZE from 8 to 4 for maximum text size reduction
- Set default font size to 8px for both mobile and desktop
- Allows very small terminal text for mobile viewport optimization

Quality gates: TypeScript check passed, production build successful
2026-05-26 21:08:26 +02:00
Alex Blank 6a0c9bd669 fix: reduce terminal font size minimum and defaults
- Reduce MIN_FONT_SIZE from 12 to 8 for smaller text option
- Reduce default font size from 14/12 to 10/10 for mobile/desktop
- Allows users to make terminal text significantly smaller

Quality gates: TypeScript check passed, production build successful
2026-05-26 21:05:04 +02:00
Alex Blank 76fbf0a755 fix: increase terminal lineHeight to 1.2 for mobile font metrics
Mobile devices use different monospace fonts (Courier on iOS, Droid Sans Mono
on Android) with larger ascent/descent metrics than desktop fonts. With
lineHeight: 1.0, calculated cell height was smaller than actual glyph height,
causing block characters to render at ~3/4 height. Increasing to 1.2 gives
mobile fonts proper vertical space while maintaining desktop compatibility.

Quality gates: TypeScript check passed, production build successful
2026-05-26 19:35:43 +02:00
Alex Blank 187193fa6e fix: terminal block character rendering by setting lineHeight to 1.0 and removing container padding 2026-05-26 19:09:06 +02:00
Alex Blank cd9c9539a2 fix: improve terminal rendering by removing CSS overrides and increasing minimum font size
- Remove CSS overrides that interfere with xterm.js internal sizing
- Increase MIN_FONT_SIZE from 10 to 12 to prevent broken character rendering
- Increase default font sizes from 10/12 to 12/14 (desktop/mobile)
- Add clamping for stored font size values to prevent old tiny values
- Remove !important rules on xterm-viewport that could cause clipping
2026-05-26 16:20:22 +02:00
Alex Blank 555517c144 fix: font size buttons only worked once due to stale callback
The changeFontSize callback passed to MobileTerminalWrapper was capturing
the initial handleFontSizeChange function, so subsequent clicks used stale
fontSize state. Fixed by wrapping handleFontSizeChange in a ref so the
callback always calls the latest version.
2026-05-26 13:51:26 +02:00
Alex Blank fc1554140f feat: significantly reduce terminal font sizes
- Reduce MIN_FONT_SIZE from 10 to 6
- Reduce MAX_FONT_SIZE from 24 to 20
- Reduce default desktop font size from 14 to 10
- Reduce default mobile font size from 16 to 12
2026-05-26 13:42:36 +02:00
Fusion adaedb70ef feat: implement mobile app usability improvements
Mobile Navigation:
- Add MobileNav component with bottom tab bar
- Show mobile nav on small screens, hide desktop sidebar
- Add session count badge to Sessions tab
- Add safe area padding for notched devices

Session Management:
- Redesign SessionCard for mobile with action menu
- Add MobileActionSheet for session actions
- Keep primary action prominent

Forms & Dialogs:
- Stack form fields vertically on mobile
- Ensure 44px minimum touch targets
- Update dialogs for 320px viewport

Responsive Layout:
- Add MobilePageHeader with back button
- Reduce page padding on mobile
- Stack multi-column grids vertically

Touch & Interaction:
- Add active states to interactive elements
- Ensure 8px spacing between touch targets

Complex Pages:
- Update Repo Workspace for mobile
- Update Tool Workshop and Config Profiles

Build: TypeScript check passes, production build succeeds
2026-05-25 11:20:25 +02:00
Fusion 9c57a94e9f Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev 2026-05-24 23:21:28 +02:00
alex 6c32e5266c fix: add terminal WebSocket diagnostics and unmount protection
- Add comprehensive connection/close/error/heartbeat logging
- Fix unmount to prevent reconnection attempts (code 1000)
- Add isUnmountingRef guard
- TypeScript compiles cleanly

Refs: intermittent terminal WebSocket failures
2026-05-24 21:20:16 +00:00
Fusion 9e88acaa36 fix: remove 0-dimension check blocking terminal fit and add debug logging
- Remove chicken-and-egg check that prevented fit() when cols/rows were 0
- Add console logging for container dimensions and fit results
- Add retry limit (50 attempts) for initial fit to prevent infinite loops
2026-05-24 23:15:15 +02:00
Fusion 21285498ae fix: mobile terminal black screen - replace grid with flexbox layout
- Root cause: CSS Grid 1fr row got 0 height inside flex parent
- Fix: Replace grid layout with flexbox column for mobile terminal wrapper
- Header and keys strip use flex-shrink: 0
- Content area uses flex: 1 to fill remaining space
- Remove debug logging
2026-05-24 23:00:32 +02:00
Fusion 9751b65dce debug: add more logging to trace mobile terminal black screen 2026-05-24 22:56:02 +02:00
Fusion 612217ad89 fix: mobile terminal black screen - grid cell had 0 height
- Root cause: .mobile-terminal-wrapper used height: 100vh inside flex parent
- Fix: Use flex: 1 instead so grid properly allocates 1fr height to content
- Add .shell.mobile-terminal-shell CSS to ensure full viewport coverage
- Remove debug logging
2026-05-24 22:51:31 +02:00
Fusion 22f736ce20 debug: add console logging to trace mobile terminal black screen issue 2026-05-24 22:46:48 +02:00
Fusion 76fbd74d20 fix: ensure terminal opens before fit and add dimension guards
- Open terminal before calling fitTerminal() to avoid race conditions
- Add container dimension checks before fitting
- Add guards to prevent fit/refresh with 0x0 dimensions
- Only send resize messages when dimensions are valid
- Prevent xterm.js internal errors from invalid dimension access
2026-05-24 21:21:34 +02:00
Fusion 51b5d723ac fix: terminal clear on reset and data loss for text starting with {
Frontend:
- Clear xterm.js screen when receiving 'connected' status after reset
- Send resize message after clearing to ensure proper dimensions
- Fixes terminal artifacts after reset

Backend:
- Fix data loss bug: text starting with '{' but not valid JSON was silently dropped
- Now writes such text to session as regular input
- Fixes missing characters when user types '{'
2026-05-24 21:15:04 +02:00
Fusion 33b482ce91 fix: terminal reconnect typing and reset functionality
Frontend:
- Fix term.onData to use wsRef.current instead of captured ws variable
- Fix fitTerminal to use wsRef.current for resize messages
- Fix sendData callback to use wsRef.current
- This fixes 'cannot type' after WebSocket reconnect

Backend:
- Add SessionRef class for mutable session reference
- Update _read_loop and _write_loop to use SessionRef
- Reset now updates session_ref.session instead of returning
- This keeps the WebSocket alive after reset instead of closing it
2026-05-24 20:57:33 +02:00
Fusion c82e628e6f fix: send stty resize on every resize with hidden command output
Backend:
- Remove _stty_sent guard to send stty on EVERY resize
- Use stty -echo to hide command, then delete the command line with ANSI escapes
- Change log level from info to debug

Frontend:
- Add window resize listener as fallback to ResizeObserver
- 250ms debounce to avoid excessive refits
- Proper cleanup on unmount
2026-05-24 20:24:41 +02:00
Fusion 5c998f5bf9 fix: revert all terminal resize fixes that caused layout issues
Reverted terminal.tsx, terminal_session.py, and terminal.py to clean state
from before the resize debugging saga. Removed:
- Debug console.log statements
- Explicit term.resize() calls that broke xterm.js
- position: relative CSS overrides on .xterm
- stty -echo wrapper and asyncio.sleep delay
- Extra requestAnimationFrame refresh calls

Kept:
- Mobile terminal features (special keys, modifiers, font size)
- ResizeObserver for container resize detection
- Basic fit() and WebSocket resize messaging
2026-05-24 20:13:10 +02:00
Fusion 3dbb6321fc fix: force explicit resize and add delayed refit after WebSocket connect 2026-05-24 19:59:35 +02:00
Fusion 3092038e40 debug: add console logging for terminal resize debugging 2026-05-24 19:44:21 +02:00
Fusion 738e01bb7c fix: add window resize fallback and delay refresh to next frame
- Add window resize listener as fallback for ResizeObserver
- Use 250ms debounce to avoid early layout reads
- Delay term.refresh() to next animation frame so renderer
  can process resize before we force redraw
- Clean up window resize listener on unmount
2026-05-24 19:31:15 +02:00
Fusion 85f04447ea fix: force xterm.js canvas redraw on resize via internal renderer 2026-05-24 18:51:15 +02:00
Fusion d931f3071d Revert "fix: add window resize listener and refresh on font size change"
This reverts commit 4a356fe88e.
2026-05-24 18:42:14 +02:00
Fusion 4a356fe88e fix: add window resize listener and refresh on font size change
- Add window resize listener to complement ResizeObserver
- Clear window resize timeout on cleanup
- Force term.refresh() after font size changes
- Send resize message after font size change
2026-05-24 18:18:41 +02:00
Fusion 4de312c170 fix: terminal resize propagation and redraw
- Frontend: Add ResizeObserver with dimension tracking for accurate resize detection
- Frontend: Fix cleanup function to properly disconnect ResizeObserver
- Frontend: Use CSS grid for terminal wrapper layout
- Backend: Add duplicate dimension check to avoid unnecessary resizes
- Backend: Ensure stty command is sent correctly to container shell
2026-05-24 17:44:00 +02:00
Fusion e7a89a853f fix: ensure terminal container fills viewport and redraws on resize
Issues fixed:
1. Terminal container now has explicit width: 100% and height: 100%
2. Added term.refresh() after fit() to force redraw when dimensions change
3. Changed shell-body from min-height to height for definite sizing
4. Added .xterm-viewport width: 100% to ensure proper filling

This ensures the terminal properly fills the viewport and redraws
content when the window is resized.
2026-05-24 17:12:32 +02:00
Fusion 7b23618ae7 fix: use requestAnimationFrame before fit() on window resize
When window resize fires, CSS layout hasn't settled yet. Adding
requestAnimationFrame ensures the browser has calculated new sizes
before xterm.js fit() reads the container dimensions. Reduced
debounce from 250ms to 100ms since rAF handles the layout timing.
2026-05-24 17:03:25 +02:00
Fusion f37813a317 revert: remove ResizeObserver and stty-on-every-resize to fix infinite loop
The ResizeObserver detected size changes caused by the stty command
output appearing in the terminal, creating an infinite resize loop:
1. Resize detected -> fit() -> send resize to backend
2. Backend sends stty command through PTY
3. stty text appears in terminal output
4. ResizeObserver detects content height change
5. fit() calculates new rows -> send resize
6. Loop continues forever

Reverted to:
- Window resize event instead of ResizeObserver
- stty command only sent once on first resize

This means the container shell stays at the initial size and won't
dynamically resize when the browser window changes, but prevents
the infinite loop.
2026-05-24 16:54:05 +02:00
Fusion 6e600fdbcd fix: use ResizeObserver for more reliable terminal resize detection
Window resize events fire before CSS layout settles, so FitAddon
was reading stale container dimensions. ResizeObserver fires after
the element actually changes size, ensuring fit() gets correct
dimensions. Reduced debounce from 250ms to 100ms for snappier response.
2026-05-24 16:50:34 +02:00
Fusion f4211ad452 chore: remove debug console.log statements from terminal component 2026-05-24 16:40:05 +02:00
Fusion 5500552993 fix: send terminal resize immediately on WebSocket connect
- Backend PTY starts with default 80x24 dimensions
- Previous code only sent resize during layout changes
- Now sends current terminal size immediately when WebSocket opens
- Ensures PTY is properly sized before shell starts rendering
2026-05-24 15:42:22 +02:00
Fusion fed49dba6d debug: add logging and simplify fit logic
- Simplified fit logic: just fit after open, after fonts load, and on resize
- Added console logging to debug what FitAddon calculates
- Single fitTerminal() function used everywhere
- Removed complex retry logic that wasn't working
2026-05-24 15:30:34 +02:00
Fusion fa17b13413 fix: wait for fonts and retry fit until proper dimensions
- Wait for document.fonts.ready before fitting (ensures correct cell metrics)
- Retry fit every 100ms if rows <= 1 or cols <= 10 (layout still settling)
- Up to 30 retries (3 seconds) for layout to stabilize
- Remove redundant delayed fits, keep only header auto-hide fit at 4s
2026-05-24 15:25:47 +02:00
Fusion 38185b9659 fix: remove container ResizeObserver causing infinite growth loop
- Container-level ResizeObserver created feedback loop with fitAddon.fit()
- Removed it, kept initialization-time dimension check only
- Rely on window resize listener for viewport changes
2026-05-24 15:19:31 +02:00
Fusion 07e7c6ea0f fix: wait for container dimensions before xterm init
- xterm docs require parent to have dimensions when open() is called
- Added ResizeObserver to wait for non-zero dimensions before initializing
- Added container ResizeObserver to handle resizes (header hide, keyboard)
- Fixed cleanup to properly disconnect observers and handle uninitialized ws
2026-05-24 15:16:11 +02:00
Fusion b638dccd36 Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev 2026-05-24 15:02:56 +02:00
Fusion 8f7e19fdb1 fix: remove conflicting CSS that broke terminal sizing
- Remove second .terminal-wrapper.mobile definition that overrode position:absolute
- Add flex display to .xterm for proper viewport filling
- Add position:relative to mobile terminal-container
- Remove manual dimension setting workaround from terminal.tsx
- Root cause: CSS specificity conflict caused FitAddon to read height=0
2026-05-24 15:02:40 +02:00
alex ba76f09a1c Merge branch 'dev' of ssh://git.commumedia.org:2222/alex/headquarter into dev 2026-05-24 12:59:36 +00:00
alex 8b08c3886c fix: prevent reconnection loop on concurrent connection close
- Don't reconnect when server closes old connection with code 4000
- Code 4000 means new connection was established, not an error
- Prevents infinite reconnection loop between old/new connections

Refs: terminal switching between 4000 error and connected
2026-05-24 12:59:28 +00:00
Fusion 5577e19782 fix: set explicit container dimensions before xterm init
- Measure parent dimensions and set them on container before term.open()
- Ensures FitAddon gets correct dimensions on initialization
- Prevents 1-row/1-col calculation that breaks scrolling and sizing
2026-05-24 14:57:03 +02:00
alex 073013bc61 feat: add heartbeat/ping to terminal WebSocket
- Backend: Send ping every 30s from WebSocket endpoint
- Frontend: Respond to pings with pongs, detect missed pings (60s timeout)
- Update type definitions to include 'resetting' status

Refs: persistent-terminal-sessions task 6.4
2026-05-24 12:45:50 +00:00
alex d1c187ab16 feat: implement persistent terminal sessions
- Terminal sessions now persist across WebSocket disconnections
- Added circular output buffer (10KB) for replay on reconnect
- Added idle timeout cleanup (30 minutes)
- Added reset functionality via WebSocket message and HTTP endpoint
- Concurrent connections close old WebSocket when new one connects
- Frontend: Added reset button with confirmation dialog
- Frontend: Handle resetting status and reconnection

Refs: persistent-terminal-sessions
2026-05-24 12:35:52 +00:00
Fusion f065e2b8c0 fix: terminal sizing and container overflow
- Change .terminal-wrapper.mobile from height:100% to flex:1 for proper flex behavior
- Add explicit width/height to xterm-viewport and xterm-screen to prevent overflow
- Add delayed fit() at 4s to resize after mobile header auto-hides
- Remove min-height:100% which caused overflow issues
2026-05-24 14:05:23 +02:00
Fusion 030a39dd5a fix: send resize message when font size changes
- After changing font size and calling fit(), send resize message to WebSocket
- OpenCode now receives correct terminal dimensions after font size adjustment
- Fixes issue where OpenCode UI didn't fill available space after font resize
2026-05-24 13:57:22 +02:00