fix(apps): stop reinstall from yanking the user out of the agent dialog

Two races around the post-install prompt:

- AppsView kept a stale selectedFolder after the open app was
  uninstalled; on reinstall the 4s apps:list poll matched it again and
  instantly swapped in the app frame, unmounting the catalog and the
  enable-agents dialog mid-choice. Clear the selection when its app
  disappears from the list.

- Bundled agents materialized on the NEXT apps:list poll, not at
  install — so the dialog's bg-task:get/patch hit a task that didn't
  exist yet if the user acted within ~4s. Install handlers now call
  syncAppAgents synchronously.
This commit is contained in:
Gagan 2026-07-07 14:58:47 +05:30
parent ec4ae4d5eb
commit 043cdc7cb2
2 changed files with 9 additions and 0 deletions

View file

@ -1646,6 +1646,9 @@ export function setupIpcHandlers() {
const preview = appInstallPreviews.get(args.name) ?? await appsInstaller.previewInstall(record);
const result = await appsInstaller.installFromRegistry(record, preview);
appInstallPreviews.delete(args.name);
// Materialize bundled agents NOW, not on the next apps:list poll — the
// renderer's post-install enable dialog patches these tasks immediately.
if (result.app) await appsAgents.syncAppAgents(result.app);
capture('app_installed', { name: args.name });
return result;
},
@ -1654,6 +1657,7 @@ export function setupIpcHandlers() {
return appsInstaller.previewUrlInstall(args.url);
}
const result = await appsInstaller.confirmUrlInstall(args.url);
if (result.app) await appsAgents.syncAppAgents(result.app);
capture('app_installed', { name: result.app.manifest?.name ?? result.app.folder });
return result;
},

View file

@ -186,6 +186,11 @@ export function AppsView({ initialAppFolder, initialVersion, onNewApp }: {
const r = await window.ipc.invoke('apps:list', {})
if (cancelled) return
setApps(r.apps)
// Drop a selection whose app no longer exists (uninstalled while
// open). Left stale, a later reinstall makes this view yank the user
// into the app frame mid-flow — e.g. while they're in the catalog's
// post-install agent dialog.
setSelectedFolder((cur) => (cur && !r.apps.some((a) => a.folder === cur) ? null : cur))
setServerError(r.serverRunning ? null : (r.serverError ?? 'Apps server is not running.'))
} catch (e) {
if (!cancelled) setServerError(e instanceof Error ? e.message : String(e))