The ExtensionUIContext interface in packages/coding-agent/src/core/extensions/types.ts is mode-specific: interactive, RPC, and print modes each provide their own implementation.[1] ExtensionContext exposes hasUI: boolean to let extensions detect whether UI interaction is available — it is false in print/RPC mode.[1] The assistant-message component in packages/coding-agent/src/modes/interactive/components/assistant-message.ts includes a null guard on content blocks, tolerating null entries in an assistant turn and preventing render-time failures when a model returns null blocks. A feature hint in feature-hints.ts surfaces the opt-in trace-sharing prompt during interactive sessions; the hint participates in hint-rotation logic and displays only to users who have not yet opted in.
ctx.ui exposes confirm(title, message), notify(message, level), setStatus(id, text) (footer status), setWidget(id, lines) (widget above editor), and custom(callback) for full TUI components with keyboard input — see Extensions for a broader orientation.[2]
The WidgetPlacement type accepts exactly two values: "aboveEditor" and "belowEditor".[1] ExtensionUIContext.setWidget defaults widget placement to "aboveEditor" when placement is not specified.[1]
ExtensionUIContext.setWorkingIndicator restores the default animated spinner when called with no argument; frames: ["●"] produces a static indicator; frames: [] hides the indicator entirely; custom frames are rendered verbatim and must supply their own color codes.[1] ExtensionUIContext.setWorkingMessage restores the default working/loading message shown during streaming when called with no argument.[1]
ExtensionUIContext.setFooter receives a ReadonlyFooterDataProvider giving access to git branch and extension statuses from setStatus(); token stats, model info, and similar data are available via ctx.sessionManager and ctx.model.[1]
ExtensionUIContext.setEditorComponent restores the default editor when called with undefined.[1] To build a custom editor with full app keybinding support (escape, ctrl+d, model switching, etc.), extensions should extend CustomEditor from @earendil-works/pi-coding-agent and call super.handleInput(data) for any keys not handled by the custom editor.[1] ExtensionUIContext.pasteToEditor triggers paste handling, including automatic collapse for large content.[1]
The AutocompleteProviderFactory type is a function (current: AutocompleteProvider) => AutocompleteProvider that wraps the current autocomplete provider to add behavior, following a middleware/decorator pattern.[1]
ExtensionUIContext.onTerminalInput is available in interactive mode only and returns an unsubscribe function.[1]
ExtensionUIContext.setHiddenThinkingLabel restores the default label for hidden thinking blocks when called with no argument.[1]
ExtensionUIDialogOptions supports an AbortSignal to programmatically dismiss dialogs and a timeout in milliseconds that auto-dismisses the dialog with a live countdown display.[1]
The ContextUsage interface reports tokens as null (not zero) when the context token count is unknown — for example, immediately after compaction before the next LLM response.[1] ContextUsage.percent is null whenever tokens is null.[1]
Sources