Skip to content

expo app improvments - #147

Merged
danielehrhardt merged 9 commits into
mainfrom
godmode/40-expo-app-improvments
Oct 11, 2026
Merged

danielehrhardt merged 9 commits into
mainfrom
godmode/40-expo-app-improvments

Conversation

@danielehrhardt

Copy link
Copy Markdown
Contributor

Phone app: faster, no more lag, and the desktop's features

The phone app now opens long chats instantly, scrolls smoothly, shows its lists at once on start, and does most of what the desktop does. I ran it in the iOS Simulator against a seeded test core. On Android it only bundles cleanly — I did not run it on a device.

Why it was slow and laggy

  • Chats: 87 % of chat bytes in your real database are inline base64 screenshots (one message is 84 MB). The phone downloaded the whole chat, uncompressed, and again on almost every event.
  • Streaming: the phone received the complete reply five times a second instead of only what changed.
  • Lists: every avatar in every list ran two or three endless animations, including on tabs you weren't looking at. Agents was a plain scroll view that mounted every row.

Measured on the seeded test core (local)

Request Before Now
Long chat (180 messages, 90 screenshots), first screen 37 MB, 1.9 s 2 KB, 0.25 s
Task board (45 tickets) 95 KB 3 KB
Chat list (200) 51 KB 4 KB

The gap will be larger over Tailscale or the cloud relay.

Core changes

All opt-in; the desktop and older phone apps get the same answers as before.

  • Message windows: a chat can be asked for its latest messages only, with older pages on demand.
  • Light messages: screenshots become their own cached image requests and long tool output is cut.
  • Compression: answers to phones and through the cloud relay are gzipped.
  • Events: stored messages go only to phones that have that chat open.
  • Task board: a summary mode leaves the long descriptions out.
  • Bug fix: Approve on a ticket always failed from the phone, because the route wasn't allowed for phones. It works now.
  • Phone allowlist: also adds follow-up controls, message pages and images, and the Android phone list and screenshot.
  • Migration 85: an index for the latest runs.

Phone app changes

  • Speed:
    • Chats open with the latest 40 messages and load earlier ones as you scroll.
    • Lists are saved on the phone and shown immediately on the next start.
    • Events patch the lists instead of refetching them.
    • Agents, Chats and Tasks are virtualized.
    • Only the streaming row re-renders while an answer arrives.
  • Questions and approvals: one tap on an option, or Approve / Decline with a note, in the chat and on Home.
  • Chat menu: rename, pin, archive, delete, pause. A scheduled follow-up can be run now, moved or cancelled.
  • In the thread: follow-up and retry markers, plan checklists, compact file diffs, and screenshots that load when you open a step.
  • New screens: archived chats (with the ones still going), archived tasks, all automations, and the activity of every agent.
  • Tickets: open instantly from the board and show their timeline.
  • Android phones: listed under Screens, watch-only.

What was checked

  • Typecheck passes for the whole workspace and the phone app; the phone app has no linter installed.
  • Core tests pass for the touched areas, run file by file, including new ones for windows, paging, light messages, the image route, gzip and the event fan-out.
  • An independent review found 14 issues; all code fixes are in. The data-layer fixes are verified only by typecheck and by the simulator run, since the phone app has no tests.
  • Simulator run: pairing, cold start from the saved lists, the long chat with paging, answering a question, the chat menu, ticket Approve, streaming, and the new screens.

Screenshots and the seed and measure scripts are in /Users/danielehrhardt/.godmode/agents/godmode/workspace/task-40-phone-app/.

Not done

  • Controlling an Android phone from the app: that widens what a paired phone may do, so it is your call.
  • Voice, a notifications inbox, the away summary, and spend/budgets.
  • Schedules read "Next run tomorrow at 08:00" rather than "Weekdays at 08:30"; the wording helper lives only in the desktop code.
  • The automatic test for the Android screenshot rule (below).

What you need to do

  1. Review and merge. Main is merged in with no conflicts left; my migration moved to 85 because main took 84.
  2. Update the desktop app after merging. The speed gains for chats need the new core; the new phone app still works against an older core, just without them.
  3. Ship a new phone build (raise the iOS build number and Android version code) and try it on a real Android phone.
  4. One rule to confirm: a paired phone gets a screenshot of an Android phone only when an agent or chat uses that phone, and can never control it. That rule has no automated test.

Task #40 · done by Godmode with Godmode Bot

…he Agents, Chats and Tasks lists

Small avatars no longer breathe and blink in every row, and every loop (avatars,
live dots, skeletons) holds still while its screen is behind another; the tabs
stay mounted, so their rows animated all the time. Streaming replies come as
what changed (deltas.patch) instead of the whole block list five times a second.
Agents, Chats and Tasks render with FlashList and memoized rows, re-render only
when run counts change, and share one chat list request.
- A chat can be asked for its latest messages only (?limit=) with older pages
  from GET /api/conversations/:id/messages?before=, and light (?lite=1):
  screenshots become their own cached requests and long tool output is cut.
  Most of a long chat's bytes are base64 screenshots.
- Answers to phones and through the cloud relay are gzipped.
- Stored messages go to a phone only for the chats it has open, light.
- GET /api/tasks?fields=summary leaves the long texts out of a board.
- Phones may approve a ticket (the app's button always got a 403) and move,
  run or cancel a chat's follow-up.
- An index for the latest runs of all agents.
…vents, probe addresses once

A chat loads its latest messages (older pages on demand) with screenshots left
out; message, task, agent and question events go into the caches instead of
refetching them, bursts of events refetch a list once, and coming back to the
app only refetches what predates the dropped link. Address probes are shared
between requests and a dead address is skipped for a while.
…t once

- Questions and approvals are answered with one tap (options, Approve / Decline
  with a note), in the chat and on Home.
- A chat's menu: rename, pin, archive, delete and pause; its follow-up can be
  run now, moved or cancelled; follow-up and retry markers, plans and file edits
  show in the thread; screenshots load on their own when a step is opened.
- Archived chats (with the ones that still go on) and archived tasks, all
  automations, and the activity of every agent.
- A ticket opens from the board's copy at once and shows its timeline.
- The lists are kept on the phone between launches; the chat renders only the
  row that streams; Home's sections render on their own.
Connected Android phones show under Screens with a picture of their screen and
open in the live viewer. A paired phone may list them and fetch a screenshot;
taking a phone over, connecting or changing one stays on the computer.
- A dead address is only skipped while another one answers, so a hiccup on the
  only address never reads as offline.
- After a reconnect everything is asked again; bursts of events wait for a
  fetch on its way and then ask once more; boards and questions are patched
  without a stale fetch landing over them.
- A message from before the loaded window no longer leaves a hole in the chat,
  a message on its way out stays until the computer's copy arrives, and the
  page of earlier messages can be tried again.
- Recycled rows keep no state of another message (approval notes, open steps).
- Android phones: a paired phone gets a screenshot only of phones an agent or a
  chat uses, and idle ones are no longer polled.
- Nothing of the settings is kept on the phone; cached pictures go with the
  pairing; screenshot polls aren't gzipped.
…mprovments

# Conflicts:
#	packages/core/src/db/migrations.ts
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant