Commit Graph

34 Commits

Author SHA1 Message Date
Daniel Brown c0eaafaf29 fix(mobile): isPassthroughMode falls back to TaskChatPanel when snapshot is missing (closes #1031) (#1034)
* fix(mobile): passthrough TUI rendering + touch-scroll

Two related mobile-UI fixes for cli_passthrough sessions, both
filed in #1031.

1. task-center-panel.tsx: align isPassthroughMode with the rest
   of the codebase by checking session.is_passthrough first. The
   memo previously only consulted agent_profile_snapshot.cli_passthrough,
   which can be undefined in the Redux store on re-mount (the snapshot
   isn't always present on the leaner session-list responses). When
   that happened on mobile, the chat panel rendered the persisted-
   messages TaskChatPanel fallback instead of the live PassthroughTerminal.
   Desktop was immune because dockview-desktop-layout.tsx already uses
   the session.is_passthrough field directly. is_passthrough is the
   source of truth used by manager_startup.go's StartAgentProcess
   routing — keeping the frontend consistent with that invariant.

2. passthrough-terminal.tsx: wire touch-drag scrolling on the xterm
   viewport. xterm.js handles mouse wheel natively but not touch
   gestures, so swiping inside the terminal on mobile bubbled up
   and scrolled the page instead of the terminal scrollback —
   effectively making everything that scrolled off-screen unreachable
   on mobile. The new hook attaches touchstart/touchmove/touchend
   handlers that map vertical drag delta to term.scrollLines(),
   gated on (pointer: coarse) so desktop xterm behaviour stays
   identical. Row-height comes from xterm's internal render dimensions
   with a measured fallback (xterm 5.x layout) and a 16px constant
   fallback if both fail.

Closes #1031

* fix(mobile): also fix useSessionLayoutState's isPassthroughMode + tighten touch-handling

Three follow-on fixes after Dan's mobile QA surfaced more cases:

1. apps/web/hooks/use-session-layout-state.ts — the mobile layout actually
   uses THIS hook's isPassthroughMode memo (not the one in
   task-center-panel.tsx that I previously fixed). It had the identical
   snapshot-only bug. Aligned with the same is_passthrough-first priority.

2. apps/web/components/task/passthrough-terminal.tsx — always preventDefault
   on touchmove (was only doing so when the row-delta calculation rounded
   to non-zero, so sub-row drags slipped through to parent scroll). Added
   touch-action: none + overscroll-behavior: contain inline on the terminal
   element so the browser never claims the gesture.

3. apps/web/app/globals.css — overscroll-behavior: none on body to block
   pull-to-refresh. iOS Safari ignores this in some configurations but
   blocking it where possible reduces the page-reload race that was
   triggering the stuck-on-loading-messages state.

* fix(mobile): trim PR to minimum required changes

After QA showed the user-visible mobile bug is fully addressed by the
useSessionLayoutState memo fix alone, revert the parallel changes to
the desktop hook (task-center-panel.tsx's useSessionApprove) and the
body-level overscroll-behavior — neither was required for the
reported bug, and Dan asked for the smallest possible diff.

Remaining changes:
- apps/web/hooks/use-session-layout-state.ts — actual mobile fix
- apps/web/components/task/passthrough-terminal.tsx — touch-scroll feature

* fix(mobile): tighten isPassthroughMode + drop terminal touch-scroll from this PR

Adversarial-review feedback applied:
- Change `is_passthrough === true` to `!== undefined` so an explicit
  server-side false isn't overridden by a stale snapshot.
- Comment now cites the specific WS handler quirk in
  ws/handlers/agent-session.ts where snapshot writes are truthy-guarded
  but is_passthrough writes are !== undefined-guarded — that's the
  concrete path where partial events land one without the other.

Dropped: the useMobileTouchScroll hook. Terminal scroll on mobile is a
separate feature that deserves its own discussion (xterm renders the
canvas above the scrollable viewport so native scroll doesn't reach the
viewport; the right fix likely lives in xterm itself or a small
event-redirect addon). Keeping this PR scoped to the rendering bug.

* fix(mobile): add minimal touch-scroll fallback for xterm viewport

xterm.js renders .xterm-screen (canvas) above .xterm-viewport, so iOS /
Android native scroll on the viewport never sees the touches and the
terminal is unscrollable on mobile.

useTouchScrollFallback wires touchstart/touchmove/touchend to
Terminal.scrollLines via an accumulated fractional-row delta. No
inertia — the proper fix is upstream in xterm-js. Gated on
(pointer: coarse) so desktop xterm behaviour is unchanged.

Sets touch-action: none + overscroll-behavior: contain inline on the
terminal element so the browser doesn't claim the gesture for
pull-to-refresh.

* fix(mobile): inertia decay on touch-scroll release for native-scroll feel

* fix(mobile): address adversarial review of touch-scroll hook

- Read xterm from ref inside each handler so renderer recreate doesn't
  strand the handlers on a stale Terminal instance (React refs are
  stable so dep array doesn't catch .current swaps).
- Drop the internal _core._renderService private-API path for row
  height in favor of public term.rows + measured element height. The
  internal path was API-unstable across xterm majors.
- Velocity window 80ms → 50ms so a direction reversal at the tail of
  the gesture is the release velocity, not averaged against the early
  motion.
- Reset pendingRows fractional accumulator on direction reversal — was
  causing perceptible stickiness when reversing from slow-up to fast-down.
- Style restoration now uses removeProperty when the inline style was
  never set, rather than leaking an empty string in its place.

* fix(mobile): revert touch-scroll hook from this PR — separate concern

After several iterations the touch-scroll fallback kept surfacing new
issues (iOS pull-to-refresh leaking through preventDefault, scroll
direction reversal edge cases) that suggest a more involved upstream
discussion is needed about whether to ship a workaround in
PassthroughTerminal at all vs fixing xterm.js's mobile story upstream.

Splitting that work out so this PR can land the rendering bug fix
cleanly. Will file a separate issue for the touch-scroll work with
the diagnosis + alternatives we explored.

* fix(mobile): honor is_passthrough when snapshot missing

---------

Co-authored-by: Carlos Florêncio <carlosmflorencio@gmail.com>
2026-05-25 22:09:17 +01:00
Carlos Florêncio f1dbad1dbd feat(cli-mode): auto-inject task prompt + dynamic submit sequence + passthrough UX fixes (#923) 2026-05-25 19:14:36 +01:00
Carlos Florêncio dbe778e4e8 feat: auto-show PR details panel when task has associated PR (#517) 2026-04-02 00:08:35 +01:00
José Almeida d1a028fdb6 feat: introduce subtasks, allow sessions to task reuse executor (#419) 2026-03-29 15:33:40 +01:00
Carlos Florêncio ea1b731fd6 feat: improve task launch (#297) 2026-02-26 23:06:07 +00:00
Carlos Florêncio a23ab5be3a feat: remote executors + secrets (#257) 2026-02-21 22:14:56 +00:00
Carlos Florêncio 61ef224ec7 style: fix format issues (#255) 2026-02-19 22:18:01 +00:00
Carlos Florêncio fe9298a7ad feat: improve ux (#254) 2026-02-19 18:05:52 +00:00
Carlos Florêncio 53ae8d57e3 fix: resolve all web app ESLint linter warnings (#246) 2026-02-18 18:24:41 +00:00
Carlos Florêncio 2b05ed0735 feat: improved passthrough and workflow (#237) 2026-02-17 12:32:02 +00:00
Carlos Florêncio 633c4e0e55 feat: improve changes panel (#234) 2026-02-16 22:43:47 +00:00
Carlos Florêncio 658bd349b5 feat: improve workflows (#228) 2026-02-16 13:48:58 +00:00
Carlos Florêncio 0a2ed53327 feat: improve plan mode (#212)
feat: plan mode
2026-02-08 20:38:28 +00:00
Carlos Florêncio 3717d6982f feat: review ux (#210)
feat: review dialog
2026-02-08 11:14:15 +00:00
Carlos Florêncio daccb38354 feat: improve file tree (#209) 2026-02-07 18:12:23 +00:00
Carlos Florêncio 4d41155158 feat: mock agent (#208) 2026-02-07 17:48:04 +00:00
Carlos Florêncio 3c7f434cda feat: improve messages ux (#193) 2026-02-06 00:13:15 +00:00
Carlos Florêncio 06f7fe9795 feat: improve session terminals (#185) 2026-02-05 04:09:04 +00:00
Carlos Florêncio b22e66750c feat: improved file tree (#164)
feat: improved editor
2026-02-03 04:14:07 +00:00
Carlos Florêncio ed6c6e8d1b fix: show approve button wrongly + improve plan ux (#158) 2026-02-02 22:45:35 +00:00
João Salavisa d951b9cb47 Fix: Persist plan notification state across page refreshes (#150) 2026-02-02 01:28:07 +00:00
João Salavisa 5bd298ddc2 feat: Add file editor with diff-based save functionality (#145) 2026-02-02 00:59:48 +00:00
Carlos Florêncio 38fb2f638f feat: pierre diffs lib (#147) 2026-02-02 00:17:23 +00:00
João Salavisa 510c2c56c4 feat: Improve task approval workflow and workflow templates (#141) 2026-02-01 22:12:28 +00:00
João Salavisa eedbfdf68a feat: plan comment annotations, Kandev system prompt, and Standard workflow (#134) 2026-01-31 23:57:56 +00:00
Carlos Florêncio 6d23d68633 feat: improve chat ui messages (#132) 2026-01-31 19:45:33 +00:00
João Salavisa 6eb24006f9 feat: implement task plans feature (#131) 2026-01-31 00:51:17 +00:00
Carlos Florêncio 859eb70908 feat: improve task switch + cli passthrough resume (#98) 2026-01-25 20:14:40 +00:00
Carlos Florêncio 66cda240e0 feat: cli passthrough setting (#93) 2026-01-25 17:49:53 +00:00
João Salavisa 39b6e89244 feat: Git status tracking refactor with persistent snapshots and commit history (#86) 2026-01-24 00:41:43 +00:00
Carlos Florêncio 1737cab44f feat: improve chat ui paddings (#83) 2026-01-23 21:21:36 +00:00
João Salavisa 8dd88e8c60 refactor: comprehensive code quality improvements (#69) 2026-01-21 19:49:36 +00:00
João Salavisa fba868d3fe feat: dynamic model switching and session status fix (#68) 2026-01-21 17:19:50 +00:00
Carlos Florêncio fb042e4c59 feat: session refactor (#30) 2026-01-17 19:02:22 +00:00