docs(sessions): document settled extension dialog cards as dismiss-stay records

This commit is contained in:
Federico Jaramillo Martinez
2026-07-29 07:52:21 +02:00
parent 5420869c52
commit 7a426571b8
4 changed files with 10 additions and 7 deletions
+1
View File
@@ -36,6 +36,7 @@ Pi extensions running under PI WEB's session daemon can ask the user questions w
- **Works from hooks, without the prompt queue.** Answers travel over a dedicated session-daemon channel, so a dialog opened inside an in-flight `tool_call` hook parks safely — the agent loop waits for the hook and the run continues with the answer. Consent-gating a tool from a `tool_call` hook is a supported pattern.
- **`session_start` dialogs are reachable.** A dialog opened from a `session_start` hook is answerable while the session is still starting, both when creating a session and when opening an existing one; startup completes once the dialog settles.
- **Survives browser reloads; first answer wins.** Reloading the browser re-renders open dialogs from the session status. With several tabs on the same session, the first answer settles the dialog and the other tabs re-render the settled card.
- **Settled cards stay until dismissed.** An answered or closed dialog leaves its outcome card in the transcript so the user can see what became of it — answers travel to the extension alone, so the card is the only record of the exchange. The card is browser-local: only a browser that saw the dialog open renders it, and switching sessions or reloading drops it.
- **Timeouts.** The extension's own `timeout` option applies, and the daemon adds an unattended-dialog safety valve, `extensionDialogsTimeoutMs` (default 5 minutes, `0` waits forever — see [Extension dialogs](https://pi-web.dev/config#extension-dialogs)). The effective deadline is the sooner of the two. A dialog that closes without an answer resolves with its kind's cancel value: `false` for confirm, `undefined` for select and input.
- **Abort and runtime replacement.** Aborting the current run settles a dialog opened during that run immediately, at abort-request time, with its cancel value. Replacing the session runtime (`/reload`, session disposal) settles any still-open dialog the same way; hooks on the new runtime open fresh dialogs. The extension's own `AbortSignal` is honored: aborting it dismisses the dialog and resolves with the cancel value.
- **Other UI surfaces are still no-ops.** `ExtensionUIContext` methods beyond the three dialogs (widgets, status, editor, `custom`) remain unimplemented under PI WEB even though `hasUI` is `true`; do not rely on `hasUI` alone to detect them.
+4 -3
View File
@@ -46,9 +46,10 @@ export interface AppState {
pendingDialogs: PendingExtensionDialog[];
/**
* Dialogs that closed while their session was selected, kept with the close
* reason and any answer so the card can render its outcome briefly. The wire
* outcome is deliberately small, so only a browser that saw the dialog open
* can show the closed card; deselection and reloads drop these.
* reason and any answer so the settled card can show what became of the
* dialog. The card stays until the user dismisses it. The wire outcome is
* deliberately small, so only a browser that saw the dialog open can show
* the closed card; deselection and reloads drop these.
*/
closedDialogs: ClosedExtensionDialog[];
/** Thinking levels available for the selected session's current model. */
@@ -76,7 +76,8 @@ export function extensionDialogCountdownText(timeoutAt: string | undefined, nowM
* The card owns only browser-local form state (the half-typed input, the
* in-flight close flag, the display-only countdown); the daemon remains the
* source of truth for whether the dialog is open. Closed mode renders the
* transient outcome for a browser that saw the dialog open.
* settled outcome a browser-local record that stays until dismissed — for a
* browser that saw the dialog open.
*/
@customElement("extension-dialog-card")
export class ExtensionDialogCard extends LitElement {
+3 -3
View File
@@ -656,9 +656,9 @@ export interface PendingExtensionDialog {
/**
* The complete result of a closed extension dialog. Unlike an ask outcome it
* stays small — the dialog itself is not embedded, because a closed dialog
* renders only transiently for browsers that saw it open; reloads rehydrate
* open dialogs from {@link SessionStatus.pendingDialogs} alone.
* stays small — the dialog itself is not embedded, because a settled card is a
* browser-local record that stays until the user dismisses it; reloads
* rehydrate open dialogs from {@link SessionStatus.pendingDialogs} alone.
*/
export interface ExtensionDialogOutcome {
dialogId: string;