Skip to content

Electron architecture: agent-host utility process, MessagePort streaming, startup wins #418

Closed

Description

@currentbits

From the Electron-architecture research (VS Code/pi-desktop pattern): agents are spawned directly from the main process today (452 child_process call sites in electron/). Move them into one utilityProcess.fork 'agent host' owning all provider child processes, streaming to the renderer via MessageChannelMain MessagePorts (structured clone, no per-message main-process hop). Keeps main responsive under agent churn and gives crash isolation.

Also from the round: module.enableCompileCache() in main (near-free startup win), Slack-style boot data (inline thread list into initial HTML — first paint shows real threads, no spinner), lazy transcripts (don't hydrate full history until a thread is selected), and a startup-time CI gate with a regression threshold. Companions to #144/#225/#359.

Activity

  1. added and removed on Oct 18, 2026
  2. currentbits commented on Oct 18, 2026

    @currentbits
    OwnerAuthor

    Status from thread d9f18846 (commit 7c8b3bf on coder/electron-architecture-agent-host-utility-d9f188):

    Shipped

    • module.enableCompileCache() at the top of electron/main.js. On Electron 35.7 / Node 22.16 the store/runner/ipc/services require graph went from about 80 ms to about 70 ms on warm launches.
    • Startup CI gate in electron/smoke.js: it times process start to the first React mount and fails above SOLENTA_STARTUP_BUDGET_MS (default 15 s). It runs on all three OS smoke jobs. Locally it measures 1.1–1.8 s, and I confirmed it fails with a 300 ms budget.

    Already on main

    Agent-host utilityProcess: on hold, needs a decision. It only works if the store moves with it:

    • Agent CLIs already run as separate OS processes, so a crashing CLI cannot take main down. Crash isolation adds little.
    • The per-event cost in main is the runner's Store work: message upserts, partial saves, broadcasts (see Performance round: measure on real data, then fix the top costs #1475 and scripts/perf/store-stream-bench.js). A host that owns only the child processes moves just the line split and JSON.parse. Each event then crosses back to main by structured clone, which costs about the same as the parse.
    • If MessagePorts sent events straight to the renderer, they would skip the Store, which owns the persisted transcript.
    • The real gain means moving runner + Store into the utility process, with ipc.js/services proxying to it. That is a rewrite of the main-process architecture.
  3. currentbits commented on Oct 18, 2026

    @currentbits
    OwnerAuthor

    Compile cache and the startup gate are in PR #1662. The agent-host work is split out to #1661, which starts by measuring main's event-loop lag under concurrent agents before any refactor. Close #418 once #1662 merges.

  4. added and removed on Oct 18, 2026
  5. currentbits commented on Oct 18, 2026

    @currentbits
    OwnerAuthor

    Landed from Solenta thread "Electron architecture: agent-host utility process, MessagePo" (PR #1662). Closed on merge.

  6. currentbits commented on Oct 19, 2026

    @currentbits
    OwnerAuthor

    Step 1 of the agent-host split-out (#1661) is measured and closed. Main is not lagging under agent churn, so there is no need to move runner and Store into a utilityProcess.

    • Bench: scripts/perf/agent-churn-bench.js (PR Add a bench for main-process lag under agent load (#1661) #1683). It runs N fake stream-json agents through the real runner, Store and IPC against a clone of the live store (1952 threads).
    • p99 main loop lag was 4–6 ms from 0 to 20 concurrent agents, including when streaming into the largest (2–3.6 MiB) transcripts. The bar was 50 ms.
    • The one thing that scales is the max stall: about 6.5 ms per agent writing into a big transcript (70 ms at 10, 132 ms at 20). It comes from Store._snapshotDirtyShards, which stringifies every dirty shard synchronously in one save. Moving the Store to another process would only move that stall, so the fix belongs inside the Store. It is offered as a follow-up chip and is not urgent.

    Full tables are on #1661.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions