pi-mono/packages
Petr Houška 80d4d3c869
fix(coding-agent): remove all extension overlays on /reload and session switch (#11853)
## Problem

`InteractiveMode.resetExtensionUI()` runs on `/reload` and before a
session is invalidated (session switch, new session, fork). For overlays
it called `this.ui.hideOverlay()` once, which pops only the topmost
entry of the TUI overlay stack.

Trace: an extension opens two overlays with `ctx.ui.custom({ overlay:
true })`, then the user runs `/reload`. Reset removes the upper overlay;
the lower one stays on screen, gets focus back and keeps receiving
input, although the extension instance that created it is gone. A hidden
overlay (`handle.setHidden(true)`) also stays in the stack and can be
shown again by stale code.

Blindly clearing the whole stack is not correct either: pi opens its own
overlays (the header logo easter egg in `components/easter-egg-3d.ts`).
With the old code, a reset while the easter egg was topmost removed the
easter egg and left the extension overlay.

## Fix

`showExtensionCustom` records each overlay it opens in
`extensionOverlays` (handle -> removal function). The same function
serves `done()` and `resetExtensionUI()`: it hides the overlay, clears
its blocked program status (#11851) and disposes its component. Deleting
the map entry first makes a second call a no-op, so a late `done()`
after reset does not dispose twice. Reset calls it for every recorded
overlay, newest first, including hidden ones. Overlays not opened by
extensions are left alone. This replaces the separate
`blockingOverlaySources` set and reset loop added in #11851.

Pending `ctx.ui.custom()` promises of removed overlays stay unsettled,
matching how reset already treats inline dialogs.

## Testing

- New regression test in `test/interactive-mode-status.test.ts`: a
pi-internal overlay plus three extension overlays (one hidden), then
reset. Checks that the extension overlays are gone and disposed, the
internal overlay remains and receives input. Fails without the fix.
- `test/interactive-mode-status.test.ts`,
`test/interactive-mode-extension-dialogs.test.ts`,
`test/interactive-mode-paste.test.ts`,
`test/suite/regressions/5943-session-start-notify.test.ts` pass.
- `npm run check` clean.
2026-11-05 23:30:54 +01:00
..
agent Anthropic message threads (#11545) 2026-11-03 14:07:57 +01:00
ai fix(ai,coding-agent): remove "(legacy)" marker from OpenAI Codex provider name 2026-11-05 22:51:36 +01:00
chord feat(p2): Chord v2 cleanup pass 2026-11-05 18:22:13 +00:00
codemode Add [Unreleased] section for next cycle 2026-11-02 11:38:21 +01:00
coding-agent fix(coding-agent): remove all extension overlays on /reload and session switch (#11853) 2026-11-05 23:30:54 +01:00
durable fix(durable): raise timeout of seeded SqliteStorage batch commit tests 2026-11-05 09:50:00 +01:00
env fix(env): kill what a process program left running when it exits 2026-11-03 14:17:21 +01:00
evals Release v1.5.0 2026-11-02 11:38:21 +01:00
mcp chore(licenses): rename dir (#11834) 2026-11-05 12:42:32 +01:00
schema fix(schema): num no longer takes nan and infinity 2026-11-05 14:20:32 +01:00
telemetry feat(chord): telemetry from pages and workers stored by the server, who a span was for 2026-11-04 11:59:14 +00:00
tui fix(tui): prevent cursor marker leaks (#9441) 2026-11-04 11:26:48 +01:00