`/mcp reauth <name>` probed the server with `{ oauth: false }` and treated a
successful unauthenticated `initialize` as proof that OAuth was unnecessary,
hard-erroring with "Server connection succeeded without OAuth; reauthorization
is not required." Per the MCP spec a server may allow unauthenticated
`initialize` while requiring a bearer token for `tools/call`, so this left no
way to acquire a credential for such servers.
When the handshake succeeds without an in-band tool challenge, fall back to
`discoverOAuthEndpoints(config.url)` and proceed with the flow if the server
advertises OAuth metadata; only refuse when no OAuth endpoint is discoverable.
Fixes#8922
InputController.#invokeSkillCommand cleared the draft and awaited the full
promptCustomMessage dispatch with no transcript render. AgentSession.#promptWithMessage
runs awaited preflight (memory recall, before_agent_start hooks, auto-thinking
classification, pre-prompt compaction) before the message reaches the agent, so a slow
step such as a Hindsight auto-recall timeout left the composer cleared with no pending
row, unlike a normal prompt's optimistic row from startPendingSubmission.
Idle skill submissions now paint an optimistic skill row before the awaited dispatch;
the canonical message_start reconciles it in place via EventController instead of
appending a duplicate. Streaming submissions still queue and show their chip.
Fixes#8895
Current Finder Cmd+C pasteboards advertise both a public.file-url and a
generated 1024x1024 file-icon bitmap. arboard::get_image() succeeded with
the icon, so handleImagePaste attached it before readMacFileUrlsFromClipboard
was reached, sending a generic PNG document icon to vision models instead of
the copied screenshot.
Probe the Darwin file URLs before the bitmap representation so an image-file
URL wins over the co-advertised icon. Pure bitmap pasteboards (screenshots,
browser copies) and non-image file URLs still fall through to the image/text
paths. readMacFileUrls is a no-op off Darwin.
Fixes#8769
Expose the Pi-compatible tui, rpc, json, or print host mode to every extension context and cover mode transitions in the runner regression suite.
Fixes#8419
- Replace the obsolete agent dashboard control center with a new fullscreen agents hub component.
- Integrate AI-assisted agent creation architect flow using model sessions.
- Provide interactive property strips and model browser integration for agent configuration.
- Update tests and documentation to support the redesigned agents hub.
- Added support for external thinking and forced reasoning disablement across AI provider options and request transformers.
- Implemented the private scratchpad think tool along with its renderer, system prompt rules, and schema configuration.
- Updated agent session management and SDK tools to support dynamic runtime activation of the think tool via the externalThinking setting.
- Added comprehensive unit tests covering reasoning fallbacks, tool activation, and rendering behavior.
showHookCustom hardcoded the overlay geometry and never read
overlayOptions/onHandle, which regressed the v0.45.6 API (PR
badlogic/pi-mono#667). Forward overlayOptions to showOverlay (keeping the
full-cover defaults as fallback), invoke onHandle with the returned
OverlayHandle, widen the options type via a shared ExtensionCustomOptions,
and re-export OverlayHandle/OverlayOptions from the extension API.
Replayed idle transcripts in bounded message and time chunks, painting cleared scrollback between macrotasks so terminal input remains responsive during restore and tree navigation. Kept streaming rebuilds atomic and migrated every rebuild caller to await completion.
Fixes#8133
The #7904 fix stopped masking provider errors as "Handoff cancelled", but
an empty or whitespace-only generation still fell through: whitespace-only
text passed the `!handoffText` guard and produced a bogus handoff, while
empty text returned undefined which the interactive /handoff caller mapped
to "Handoff cancelled" with no detail and no log entry.
Treat empty/whitespace-only output as a real failure: a user-initiated
handoff throws "Handoff generation produced no content" (surfaced as
"Handoff failed: ...") and logs it; auto-handoff keeps returning undefined
so maintenance falls back to context-full compaction. Also log genuine
handoff failures in the command controller so they persist for debugging.
Fixes#7993
- Gated model-issued approval dialogs on the TUI tool preview lifecycle.
- Finalized edit arguments before waiting for the asynchronous diff.
- Added regression coverage for both the preview gate and approval ordering.
Fixes#7957
The handoff catch in session-handoff.ts and the /handoff handler in
command-controller.ts mapped any error named AbortError to "Handoff
cancelled" regardless of whether the handoff signal was actually
aborted. Providers throw name-AbortError errors on non-user conditions
(stalls, idle timeouts, nested resolution failures), so a genuine
generation failure surfaced as a user cancellation and hid the cause.
Only report "Handoff cancelled" when handoffSignal.aborted is set;
re-throw the real error otherwise. The controller now trusts the
normalized "Handoff cancelled" message and drops its own AbortError
check so re-thrown provider failures render as "Handoff failed: ...".
Fixes#7903
app.tools.expand (Ctrl+O) was wired only through the editor's input path,
so when a tool-approval prompt or other selection dialog took keyboard
focus the key was delivered to that component and never reached the expand
handler — a large truncated edit could not be expanded while the user was
deciding whether to approve or deny it.
Promote the shortcut to a global TUI input listener (matching the existing
debug and branch/copy shortcuts) so it fires regardless of focus. It defers
when the main transcript is not the active surface (a fullscreen/anchored
overlay: agent hub, transcript viewer, log viewer, model picker) or when the
focused component rebinds Ctrl+O for its own use (the tree selector's filter
cycle). The editor-scoped handler is removed as a clean cutover.
Fixes#7837
- Routed session tool provenance through live and rebuilt transcript render paths.
- Kept same-named extension tools on the generic renderer while preserving native tool rendering.
- Added regression coverage for an external recall result collision.
Fixes#7770
The ExtensionAPI getAllTools() wired to session.getAllToolNames(),
returning bare tool-name strings. Upstream @earendil-works/pi-coding-agent
promises ToolInfo[] with sourceInfo, so extensions loaded through the
legacy-pi shim (e.g. gentle-pi) crashed on t.sourceInfo.source at every
session start.
Added SourceInfo/ToolInfo types plus SessionTools.getAllToolInfos(), which
returns { name, description, parameters, sourceInfo } and classifies each
tool as builtin/mcp/sdk/extension. Rewired every getAllTools action site
(interactive, acp, print/rpc, subagent executor) and the example extension.
Fixes#7732
- Implemented in-house, zero-dependency utility modules in `pi-utils` covering DOM manipulation, markdown parsing, templating, browser automation helpers, and terminal buffers.
- Migrated packages across the repository to consume the new internal utilities and `omptype` schema validators instead of external dependencies.
- Removed multiple external runtime and development dependencies including Zod, Marked, LRU cache, Turndown, and Puppeteer browser packages.
Repeated /mcp reauth commands could remain blocked by a prior
unfinished login because each command receives a fresh controller.
Coordinate flows through session-shared state so a replacement cancels
and cleans up the old flow before proceeding.
After the fullscreen Plan Review closed on approve-and-execute, the
conversation view stayed blank while the plan ran. The propose write's
tool_execution_end handler runs inside EventController's serialized
dispatch chain and awaited handlePlanApproval, which awaits session.prompt
for the entire execution turn, so every later agent_start/message_start/
tool/message_update event queued behind it until the run finished.
Detach the approval dispatch so the dispatch link settles immediately and
the execution turn's events render live. Follow-up to #5688, which only
moved the overlay close before the still-blocking dispatch.
Fixes#7684