- Introduced `Max` as a first-class reasoning effort tier across all packages, including AI providers, coding agent configurations, and RPC protocols.
- Refactored model effort ladders to use wire-exact mappings and removed legacy effort aliasing (e.g., `max-to-xhigh` mapping).
- Updated model registry and provider configurations to support `Max` tier routing, color themes, and UI icon associations.
- Expanded test suites to provide end-to-end coverage for the new reasoning tier, including updated compatibility and fallback scenarios.
The token-usage row shown under assistant messages (display.showTokenUsage) now leads with the turn's local wall-clock time down to the second (YYYY-MM-DD HH:mm:ss), sourced from the assistant message's persisted timestamp so live, rebuilt, and restored transcripts all show the turn time rather than the view time.
createUsageRowBlock takes timestamp as an optional trailing argument, preserving its (usage, durationMs, ttftMs) public call contract on the package's ./modes/components/* export surface.
Two review findings on the blocked-todo support:
- A blocker `reason` with an embedded newline corrupted the Markdown
round-trip: `phasesToMarkdown` writes the note as a trailing HTML comment
on one checklist line, so a newline split it across two lines — the first
an unclosed `<!-- blocker: …`, the second an unrecognized-syntax error —
losing the reason on `/todo edit` and export/import. Normalize the reason
to a single line (collapse whitespace runs) at the `block` op source, so
the round-trip, HUD, and summary consumers all stay one-line-safe.
- The todo prompt now directs the agent to `block` a task waiting on
another agent, but `#reconcileTodosWithSubagents` only auto-completed
pending/in_progress todos. A todo blocked on a detached subagent would
stay blocked after that subagent completed, and since blocked todos are
excluded from the stop reminder it stranded silently. Include `blocked`
in the reconciliation (a matching subagent completing is the unblock
signal) and drop the now-stale blocker note when completing.
Both paths are revert-proven by new regression tests.
Co-Authored-By: seal <noreply@sealedsecurity.com>
The throttled jj branch/status caches guarded in-flight results only by
root equality (`#jjRoot === root`). When a HEAD or bookmark move fires the
git watcher's `invalidate()` while a query for the *same* root is still in
flight, `#invalidateGitCaches()` resets `#jjRoot` but the next render
re-resolves it to the identical root string — so the root-only guard
accepts the pre-invalidation result, caches a superseded bookmark/status,
and advances the 5s throttle on it. The stale label then persists for a
full TTL after the move.
Replace the root-equality guard with a generation token bumped on every
cache reset (cwd switch in `#jjRootFor` and HEAD/bookmark move in
`#invalidateGitCaches`). Each query captures the generation at launch and,
on resolve, drops its result and refuses to advance the throttle if the
generation changed. This subsumes the old root check (a root change always
resets, bumping the generation) and additionally catches the same-root
case it structurally could not.
Regression test (revert-proven): a same-root invalidation mid-flight
renders the stale label without the fix, is dropped with it.
Co-Authored-By: seal <noreply@sealedsecurity.com>
Added an explicit timeout presentation capability so interactive queued dialogs defer the fallback while older UI implementations still get an immediate tool-owned timeout.
Refs #4995
Whole-repo `biome check .` (CI `check:tools`) failed on the jj-cache
test with two diagnostics that a changed-files-only local check missed:
- assist/source/organizeImports (error): the named imports in
`import { settings, Settings }` were unsorted. Fixed via biome's safe
autofix -> `{ Settings, settings }`.
- suppressions/unused (warning): a `biome-ignore
noControlCharactersInRegex` sat on the `visible()` helper, but biome
does not flag the `\xNN` escape-sequence form used there, so the rule
never fired and the suppression had no effect. Removed it per biome's
own instruction; the regex is unchanged.
No behavioral change: the jj-cache test still passes (2/2).
Co-Authored-By: seal <noreply@sealedsecurity.com>
The run-state `working` spinner arms a periodic setInterval that re-emits
the terminal title as an OSC-0 write each tick. shutdown() restored the
shell title via popTerminalTitle() but never stopped the interval, so a
pending tick could fire after the restore and leave the parent shell tab
reading a stale spinner title post-exit. Wire the existing
disposeTerminalTitleState() into shutdown() before popTerminalTitle().
Co-Authored-By: seal <noreply@sealedsecurity.com>
Reset the run-state title to idle when focusing an idle session (was inheriting the previous session's stuck spinner); drive the title to attention while a tool blocks on an approval prompt (not just ask), returning to working at its end; let an extension setTitle() own the terminal verbatim so neither the run-state prefix nor the spinner tick clobbers it, cleared when the app sets an authoritative session title; use NodeJS.Timeout for the spinner timer field.
The terminal title (OSC 0) now carries a run-state prefix: an animated spinner while the agent is working and a steady dot when idle, so a backgrounded tab/pane shows which session is busy vs done. `setTerminalTitleState` also exposes an `attention` ([!]) state for callers; rendering is gated by `tui.titleState` (default on), dedups writes, and is TTY-guarded.
Refs can1357/oh-my-pi#3587
Reset the ask tool fallback timeout whenever the interactive selector resets its UI countdown, preventing late keypresses from falling back to the original recommended option.
Refs #4995
Switched interactive OAuth login to start model discovery in the background after credentials are saved.
Added a regression test that keeps model refresh pending and asserts the success transcript appears immediately.
Fixes#4989
Left Darwin stdio MCP server launches in the inherited session so macOS TCC can prompt for Apple Events permissions used by xcrun mcpbridge.
Added resolver coverage for Darwin while preserving Linux detach and Windows console behavior.
Fixes#4987
Magic keyword matching now treats sentence punctuation and quotes as prose boundaries while still rejecting casing changes, inflections, and path/file-extension occurrences.
Added regression coverage for detection and highlighting across ultrathink, orchestrate, and workflowz.
Fixes#4965
- Added auto-sealing logic to `FinalizableBlock` to finalize displaceable snapshots when they enter the scrollback area.
- Updated TUI frame emission to publish committed rows and clamp them to segment bounds, ensuring accurate component updates.
- Introduced component tracking and cleanup in event controller tests to prevent resource leaks during finalization.
- Validated state transitions and post-emit synchronization through comprehensive new test suites for transcript and TUI components.
The assistant message_end fan-out is fire-and-forget in the session layer
and can be parked on extension delivery while agent_end is flushed through
#endInFlight, so agent_end can overtake it. #finishPrompt then unsubscribes
the prompt turn and the mapAssistantMessageEnd fallback never runs: an ACP
client that only received agent_thought_chunk updates (thinking streamed,
text arrived only on the trailing message) stays stuck on the thinking
block with no visible answer. On agent_end, emit the last assistant
message's text before resolving the prompt when live-message progress shows
no text was ever delivered, and defer the live-state reset past that flush
so a late message_end cannot resurrect fresh progress and double-emit.
Fixes#4902
The first-result viewport-repaint gate assumed only streamed
__partialJson placeholder shapes (SSH) could re-anchor; the write
renderer's collapsed pending preview paints a tail window from decoded
content, so its first partial result re-anchored to the top of the file
and left the committed tail rows stale above the new frame.
Resolve forceFirstResultViewportRepaint per renderer as a boolean or an
(args, options) predicate evaluated at paint time: write opts in when a
collapsed preview outgrew the streaming tail window, SSH stays scoped to
the streamed-placeholder shape it always covered.
Adopted from PR #4478 (roboomp) with an allocation-free line-count scan
and terminal-buffer regression coverage.
Fixes#4477
Esc during an active streaming turn required a second press within 2s
(two-step arm from #3493). In the no-input-waiter submit path the turn
starts with isStreaming=true but no working loader, so Esc fell into
the two-step branch and the agent_start subscription then wiped the
arm — repeated presses kept re-arming and never aborted. The loader-up
path already aborted on a single press, so the confirmation guarded no
coherent state. First Esc now aborts the streaming turn directly.
Adopted from PR #4938 (test + input-controller + changelog hunks only;
unrelated workflow-notice.md churn dropped).
Fixes#4921
Extensions calling ctx.ui.addAutocompleteProvider (e.g. @ff-labs/pi-fff)
crashed at load with 'TypeError: ... is not a function' because omp's
ExtensionAPI.ui omitted pi's autocomplete-provider API; the throw also
aborted the rest of a try/catch-guarded session_start init.
ExtensionUIContext now declares addAutocompleteProvider(factory).
Interactive mode stacks each factory on the built-in editor provider in
registration order, re-applies the stack on every slash-command refresh,
and skips throwing/malformed factories; RPC, ACP, and headless contexts
accept the factory as a no-op, matching upstream pi's RPC behavior.
Fixes#4919
Extension sendUserMessage() without deliverAs fell through to prompt(),
which throws AgentBusyError during an active stream; the message was
dropped and surfaced as 'Extension sendUserMessage failed'. Route the
omitted-deliverAs path through prompt() with streamingBehavior 'steer'
so streaming queues a steer with normal prompt-flow side effects
(keyword notices, advisor auto-resume reset) and idle still starts a
turn.
ACP skill-command prompts now pass streamingBehavior 'steer'; the RPC
skill fast-path honors the prompt command's streamingBehavior field
(default steer) like the plain-prompt path already did. Documented the
extension-facing delivery semantics.
Synthesized from PR #4942 (prompt-flow steer routing, docs, tests) and
PR #4922 (RPC streamingBehavior threading, steer regression test);
dropped PR #4942's unrelated workflow-notice.md ellipsis churn.
Fixes#4923
Co-authored-by: roboomp <omp@can.ac>
Co-authored-by: metaphorics <metaphorics@users.noreply.github.com>
The v16.3.12 explicit `selector` field (ff3b0c795c) was consumed by the
read tool but never threaded into the TUI renderers: ReadRenderArgs in
both readToolRenderer (read.ts) and ReadToolGroupComponent only derived
selectors from path-embedded `:sel` suffixes, so split-arg calls like
{ path, selector: "2-3" } rendered bare paths without line ranges or
raw modifiers.
Joined the explicit selector (trimmed, leading colons stripped, non-string
guarded) back onto the display path in renderCall, renderResult error and
success branches, and the grouped read summary, keeping hyperlinks on the
base path only.
Adopted from PR #4904 (both commits squashed), minus its unrelated
workflow-notice.md prompt churn.
Fixes#4899
- Wrote a one-shot stderr working indicator before text print-mode prompts wait on the model.
- Covered pending text/json print-mode behavior with focused tests.
Fixes#4901
Reset the jj label/status caches in invalidateGitCaches so a watcher HEAD move refetches; key the async jj lookups by their captured root so a mid-flight repo switch can't land one repo's label/counts in another's cache; thread effectiveGitCwd through the jj lookups so an active child repo uses its own jj root. Gate jj status on a detached/absent git HEAD (mirroring the jj branch overlay) so a nested ordinary git checkout under a jj workspace keeps its own git status instead of the ancestor jj status. Adds cache-coherence + mid-flight-race regression tests.
Carry task.blocker through AgentSession clone so a blocker reason survives storage round-trips; skip non-open tasks when blocking a phase so completed/abandoned work is never reopened; reject targetless block/unblock; render blocked rows distinctly (warning fg + reason) in the tool renderer and keep them visible in the collapsed HUD. Adds regression tests (red-green verified on the clone path).