This repository has been archived on 2026-07-17. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
codespace/web
tao.chen c647bb98a9 fix(web): break the terminal resize loop properly
The previous 'stabilize useMutation results' fix addressed one cause
of /shell/resize being spammed (the mutation object identity), but
not the actual root cause: a closed loop between xterm's onResize
callback, ResizeObserver, and the backend.

The full loop:
  1. ResizeObserver fires
  2. fitAddon.fit() runs
  3. fit() calls terminal.resize(cols, rows)
  4. terminal.onResize(cb) fires the listener
  5. cb calls resize.mutate() — POSTs to /shell/resize
  6. server calls pty.Setsize
  7. bash receives SIGWINCH and redraws the prompt
  8. the new output writes to the terminal, which can shift a
     scrollbar / padding by a few pixels
  9. ResizeObserver fires again
  -> repeat

Fixes applied to TerminalPanel's terminal-init useEffect:

  - Drop the terminal.onResize subscription entirely. Per the xterm
    + FitAddon pattern, the right way to push size to the backend
    is: from the ResizeObserver path, call fit(), then read
    terminal.cols/rows synchronously and call resize.mutate().

  - Dedupe by (cols, rows) — if the size hasn't changed since the
    last reported size, skip the mutation.

  - Dedupe the ResizeObserver callback by container
    getBoundingClientRect — sub-pixel changes (e.g. a scrollbar
    appearing) won't trigger a redundant fit().

  - Depend on the stable sendResize function (the destructured
    mutate from useMutation) rather than the whole resize object,
    so unrelated render churn can't tear down and re-create the
    terminal.

  - Run an initial fit() at mount so the backend learns the real
    size before the user starts typing.

The 100ms debounce was a band-aid that didn't actually break the
loop — it only slowed it down.
2026-07-06 18:23:11 +08:00
..
2026-07-02 16:57:37 +08:00
2026-07-02 16:48:19 +08:00
2026-07-02 16:48:19 +08:00
2026-07-02 16:48:19 +08:00
2026-07-02 16:48:19 +08:00
2026-07-02 16:48:19 +08:00

codespace-web

Frontend IDE shell for the codespace Go backend.

Scope

This package is the codespace web IDE. It connects to the Go backend: the file explorer and editor call the file APIs, the toolbar drives the process start/stop/restart endpoints, and the terminal streams the running OpenCode process over the WebSocket endpoint /api/workspaces/:id/process/ws.

Commands

Command Purpose
pnpm install Install dependencies
pnpm dev Start the Vite dev server (proxies /api and /healthz to http://localhost:8080)
pnpm lint Run ESLint
pnpm build Type-check and build for production

Stack

  • Vite + React 19 + TypeScript
  • Tailwind CSS v4
  • react-router v7
  • Zustand for local UI state
  • TanStack Query for API state
  • @monaco-editor/react editor wrapper
  • @xterm/xterm + @xterm/addon-fit terminal wrapper
  • react-resizable-panels for layout splits
  • lucide-react for icons

Non-goals

  • Authentication
  • i18n
  • Tests (no test framework until business logic is added)