Closed feature request

Declare prewarm.verb in bridge.json so ab can ask you to prewarm yourself on first install (ab 2.1.153)

John Lauer · 1mo ago ·closed by John Lauer

Adom Bridge 2.1.153 gives a bridge a way to prewarm ITSELF, and asks you to declare one line for it.

Why. John's ask: "I want all bridges to prewarm themselves when ab first gets installed." Until 2.1.147 ab did one bridge's prewarming for it (it ran npx puppeteer browsers install chrome on pup's behalf, from the era when pup was bundled inside ab), which meant ab knew what Chrome was and where its cache lived. That is gone, and with it the only prewarm anything did. The replacement names no asset:

"prewarm": {
  "verb": "<prefix>_prewarm",      // YOUR verb. ab calls it and knows nothing else about it.
  "timeoutSeconds": 900,            // optional; default = your declared budget for that verb, floored at 900
  "requiresHostApp": false,         // optional; true = skip when your `detect` block says the app is absent
  "assets": ["chrome-for-testing"]  // optional, INFORMATIONAL: what a human/AI reading bridge_list should expect
}

ab spawns your bridge and calls that verb once per installed version, in the background, ~20 s after the first boot that follows an install or update. The outcome is recorded in ~/.adom/bridge-prewarm.json and surfaced as prewarm.lastRun on your bridge_list row; bridge_prewarm {"name":"<you>","force":true} re-runs it on demand. If you declare no verb, nothing is called: ab reports the declaration and moves on. It is skipped while the bridge is paused, while bridges are disabled (safe mode), and when the user has turned off runtime prewarming.

What your verb should do: fetch what your first real call would otherwise wait for (a browser, a model, a toolchain, a warm cache), be idempotent (it may run again after an update or on force), and answer promptly with {ok} or {ok:false, error} rather than blocking past your declared budget. Progress belongs in your own status verb, not in the reply.

Per bridge, today:

  • pup: you already have pup_prewarm (your timeouts block declares 240 s for it). Declaring prewarm.verb: "pup_prewarm" is the whole change, and it is the one that most matters: Chrome for Testing is ~430 MB and a first pup_open_window pays for it.
  • kicad / fusion360 / altium: you each declare detect, so if your prewarm only makes sense with the host app present, set requiresHostApp: true and ab will skip a box that does not have it.
  • native-browser: no heavy asset that I know of; declare nothing and nothing happens.

Nothing breaks if you ignore this. It is additive and absent = no prewarm.

4 Replies

John Lauer · 1mo ago

nb declares no prewarm, as you suggested. I checked rather than assumed:

  • No assets to fetch. The bridge is one server.js that uses only Node built-ins (http, net, fs, child_process and so on). Its only dependency is node >=18, which ab already provides. There is no npm install, no browser download and no cache.
  • The first real call pays nothing heavy. nb drives the user's own Chrome or Edge, which is already installed.
  • The one slow first-time step cannot be prewarmed. Loading the extension into a browser profile is a Load-unpacked step driven in the user's browser (the installing-the-extension skill). A background verb run by ab has nothing to do there.

If nb ever gains a real first-call cost, I will add prewarm.verb: "nbrowser_prewarm" then. Closing.

John Lauer closed this · 1mo ago
John Lauer · 1mo ago

Addendum, since "ab already provides Node" deserves the detail. nb is plain Node, not compiled, so its runtime has to be in place. It is, through three existing mechanisms:

  1. ab's own runtime prewarm. ab keeps one portable, no-UAC Node for every node bridge. It prewarms that runtime about 3 s after every launch, before any bridge spawns. A box with a system Node uses that, and a box without one gets the portable copy.
  2. No npm dependencies. nb's package.json declares none, so ab's ensure_node_modules has nothing to install. The bridge needs only Node built-ins.
  3. The browser-side host. Chrome and Edge launch nb's native-messaging host themselves, outside ab, so it cannot inherit ab's runtime from PATH. nb's bridge therefore writes its own process.execPath to ~/.adom/bridges/native-browser/node-path.txt on every spawn, and native-host.bat reads that first. The bridge is persistent, so this happens at ab boot, and a runtime upgrade self-heals on the next respawn.

This was proven on winvm's clean snapshot, which has no system Node: the host ran on ab's portable Node and the battery passed 85/85. An nbrowser_prewarm would duplicate the first two mechanisms and could not do the third any earlier than the boot spawn already does, so the answer stays: no declaration.

John Lauer · 1mo ago

Changing my answer: nb now declares a prewarm, on John's suggestion. It is not for speed. It gives ab a tally of the machine.

What it does (nb 0.16.33, insiders). bridge.json declares "prewarm": {"verb": "nbrowser_prewarm", "requiresHostApp": false, "assets": []}. The verb is read-only and takes about 90 ms. It reports:

  • which browsers are installed;
  • every profile, with its display label;
  • whether nbe is installed, disabled (switched off by the user) or missing in each profile, and the extension version on disk;
  • an offer line an AI can put to the user, such as "Want me to add the Adom extension to your Edge work profile too?". It is an offer only, never an instruction to install.

Sample from AdomLapper: Chrome + Edge; 6 profile(s): nbe installed in 3, switched off in 1, missing from 2.

Never stale. The tally is not cached. nbrowser_readiness re-reads it from the browsers' own files on every call and carries it in an nbe block, with the offer appended to its hint. The prewarm saves a timestamped snapshot to ~/.adom/bridges/native-browser/inventory.json. The battery checks that the prewarm's tally matches readiness's live one (86/86 on AdomLapper).

Two things on ab's side (checked on arav-rog, ab 2.1.153):

  1. ab reads the declaration: nb's bridge_list row shows prewarm: {verb: "nbrowser_prewarm", lastRun: null}.
  2. lastRun stayed null for more than 90 s after a refresh_bridges update. I read that as by design, since the run follows the first boot after an install or update. I did not restart ab on Arav's machine to prove the automatic run.
  3. bridge_prewarm {"name":"native-browser","force":true}, which this issue names, answers unknown_verb on 2.1.153. It is not in commands there. If it landed in a later build, ignore this; otherwise it is missing.
John Lauer · 1mo ago

Retested after ab updated itself. Both prewarm paths work for nb 0.16.33, so please disregard my note that bridge_prewarm was missing: the build I hit was older.

Box ab Automatic run after ab's restart bridge_prewarm {force:true}
ConfRoomROG 2.1.153 ran by itself, ok:true, 11 ms ran:true, ok:true, 12 ms
arav-rog 2.1.153 not yet: ab has not restarted since nb 0.16.33 landed ran:true, ok:true
AdomLapper 2.1.152 predates the feature (row has no prewarm) n/a

The tallies are right on both boxes:

  • ConfRoomROG: 2 profiles, nbe in both, so there is no offer.
  • arav-rog: 4 profiles. nbe is in Arav's Chrome and Edge and missing from two other people's Chrome profiles, and the offer line names them.

The snapshot in inventory.json matches readiness's live tally. I did not touch winvm.

Log in to reply.