From 3c4a6b3e68181a21a92b67b8620f9e858ea3996d Mon Sep 17 00:00:00 2001 From: Nowaker Date: Tue, 6 Oct 2026 22:24:19 -0500 Subject: [PATCH] fix(tui): stop blocking first render on the full provider catalog The blocking bootstrap waited for GET /provider, which returns every models.dev provider and model: 6.6 MB, 226 providers and 8,405 models for an install with one provider connected. Building and encoding it costs the server worker 1.2 s warm (4.1 s on first call) on a loaded host, and the TUI parses all of it before the prompt can appear. Only the connect dialog reads provider_next, and the store already starts with an empty value, so the request moves to the non-blocking group that runs after the prompt is shown. Launch to a typable prompt, compiled binary, macOS M2 Pro, median (min-max) of 10 relaunches in ABBA order: home screen 2235 (2183-2277) ms -> 1976 (1928-2048) ms 3,906-message session 2575 (2523-2625) ms -> 2331 (2295-2421) ms --- packages/tui/src/context/sync.tsx | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/tui/src/context/sync.tsx b/packages/tui/src/context/sync.tsx index 71e050d11e68..20cfc33d1b39 100644 --- a/packages/tui/src/context/sync.tsx +++ b/packages/tui/src/context/sync.tsx @@ -456,7 +456,6 @@ export const { // blocking - include session.list when continuing a session const providersPromise = sdk.client.config.providers({ workspace }, { throwOnError: true }) - const providerListPromise = sdk.client.provider.list({ workspace }, { throwOnError: true }) const capabilitiesPromise = sdk.client.experimental.capabilities .get({ workspace }, { throwOnError: true }) .then((x) => x.data) @@ -469,7 +468,6 @@ export const { const configPromise = sdk.client.config.get({ workspace }, { throwOnError: true }) await Promise.all([ providersPromise, - providerListPromise, capabilitiesPromise, agentsPromise, configPromise, @@ -478,7 +476,6 @@ export const { ]) .then(async () => { const providersResponse = providersPromise.then((x) => x.data!) - const providerListResponse = providerListPromise.then((x) => x.data!) const capabilitiesResponse = capabilitiesPromise const consoleStateResponse = consoleStatePromise const agentsResponse = agentsPromise.then((x) => x.data ?? []) @@ -487,7 +484,6 @@ export const { return Promise.all([ providersResponse, - providerListResponse, capabilitiesResponse, consoleStateResponse, agentsResponse, @@ -495,17 +491,15 @@ export const { ...(sessionListResponse ? [sessionListResponse] : []), ]).then((responses) => { const providers = responses[0] - const providerList = responses[1] - const capabilities = responses[2] - const consoleState = responses[3] - const agents = responses[4] - const config = responses[5] - const sessions = responses[6] + const capabilities = responses[1] + const consoleState = responses[2] + const agents = responses[3] + const config = responses[4] + const sessions = responses[5] batch(() => { setStore("provider", reconcile(providers.providers)) setStore("provider_default", reconcile(providers.default)) - setStore("provider_next", reconcile(providerList)) setStore("capabilities", "experimentalBackgroundSubagents", capabilities?.backgroundSubagents === true) setStore("console_state", reconcile(consoleState)) setStore("agent", reconcile(agents)) @@ -518,6 +512,10 @@ export const { if (store.status !== "complete") setStore("status", "partial") // non-blocking void Promise.all([ + // Every known provider and model (megabytes); only the connect dialog reads it. + sdk.client.provider + .list({ workspace }, { throwOnError: true }) + .then((x) => setStore("provider_next", reconcile(x.data!))), ...(args.continue ? [] : [sessionListPromise.then((sessions) => setStore("session", reconcile(sessions)))]), consoleStatePromise.then((consoleState) => setStore("console_state", reconcile(consoleState))), sdk.client.command.list({ workspace }).then((x) => setStore("command", reconcile(x.data ?? []))),