- Added a `showHeader` option to shell rendering and suppressed the bash frame title bar by default.
- Parsed trailing raw-output artifact notices and folded their IDs into status footer metadata instead of command output.
- Added regression coverage for EventController to collapse single-read completions into one read group.
- Added assertions that visible reasoning breaks grouping and finalizes the prior read block.
- Added nested-live task rendering test for static task header while the task body shimmers.
- Added task-progress rendering tests for shimmered task-name rows and spinner-disabled fallback.
- Added a ToolExecutionComponent timing test validating bash spinnerFrame increments on 30fps cadence.
- Added a new SessionManager.forkFrom test confirming terminal breadcrumb suppression while cloning source session history under a new parent session.
- Updated TanCommandController test fixtures with required assistant message API, provider, model, and completion metadata.
- Added `/tan` slash command registration and interactive handling.
- Added TanCommandController validation and async task scheduling for `/tan` dispatch.
- Added session cloning that suppresses breadcrumbs, copies artifacts, and handles abort cleanup.
- Added `promptCacheKey` support in Agent and inherited `providerPromptCacheKey` in session creation.
- Added optional `reason` parameters to `Agent.abort` and `AgentSession.abort` APIs.
- Passed abort reasons through interrupt flows into underlying agent cancellation.
- Replaced hard-coded abort text with `resolveAbortLabel` for streaming and replayed messages.
- Fell back to generic `Request was aborted` text when no abort reason was provided.
- Removed the built-in `background` (`bg`) slash command and its `handleBackgroundCommand` path from the interactive flow.
- Deleted background event subscription and shutdown handling by removing `handleBackgroundEvent` from the event, input, and interactive controllers.
- Simplified `InteractiveModeContext` by dropping background-only fields and helpers such as `isBackgrounded`, background UI context creation, and background event callbacks.
- Added SGR mouse input handling for wheel and click actions, mapped to option, ToC, and body targets.
- Added deleted-heading state to undo snapshots so removed titles persist and restore correctly.
- Updated the plan-mode active prompt to require decision-complete, implementation-ready plans.
- Enabled mouse tracking for fullscreen overlays and asserted mouse-on/off sequences in tests.
- Added section-based plan parsing with per-section delete, undo, and annotate.
- Added Tab/Shift+Tab focus regions and per-line scroll navigation.
- Added Refine feedback loop emitting annotations back to the model.
- Added `OverlayOptions.fullscreen` borrowing the terminal's alt screen buffer.
- Added ChatBlock and ChatBlockHost with mount, finish, and dispose lifecycle callbacks.
- Added InteractiveModeContext.present and resetTranscript APIs and used them to mount/repaint blocks.
- Reworked controller rendering paths to emit command, event, extension, and selector outputs via ctx.present.
- Implemented component and container dispose hooks in tui so loaders and child blocks cleanup timers/effects.
- Centralized transcript spacing by stripping blank edges and inserting separators.
- Removed per-component leading spacers and empty placeholders that added extra gaps.
- Introduced TranscriptBlock grouping so related outputs render as single transcript children.
- Updated transcript-related tests to validate one-row block separators and blank-line trimming.
- Replaced the plan review flow to open PlanReviewOverlay for approvals.
- Added scrollable markdown plan rendering with prompt, options, and footer in the overlay UI.
- Added disabled-option handling so cursor movement and confirmation skip unavailable rows.
- Added setPlanContent updates to refresh overlay text and reset scroll position on edits.
- Replaced regex code-block parser with line scanner masking fences.
- Exposed `>`-quoted runs as drillable copy targets per message.
- Added combined "all quotes" target when multiple quotes exist.
- Shared immutable model registries and auth storage via beforeAll/afterAll.
- Swapped fixed-delay settle sleeps for predicate polling and signals.
- Stubbed network/timers to drop wall-clock waits in registry and history tests.
- Added resetDisplay invalidation tests and startup-timing breakdown lines.
- Added `TUI.resetDisplay()` to force an immediate full-frame replay including native scrollback.
- Moved the persistent model selector default from Ctrl+L to Alt+M, preserving existing user remaps.
- Reserved Alt+M so extensions cannot shadow the model selector shortcut.
- Emitted per-command cmd:N targets after the assistant message that issued them.
- Carried commands from text-less messages to the next visible message.
- Replaced the single trailing "last command" leaf.
- Updated EventController to keep foreground render mode active from agent_start through agent_end so live-region rebuild remains enabled during a turn.
- Pinned stop-reason assistant errors to the editor banner and suppressed the transcript's inline Error line while pinned, then restored it on the next agent_start.
- Added tests covering error-banner suppression/restoration and eager native scrollback rebuild ordering before loading animation.
- Added a fullscreen /copy tree of recent assistant messages with nested code blocks and a live preview pane.
- Removed the /copy last|code|all|cmd subcommands in favor of tree selection.
- Extracted copy-target assembly into a testable util.
- Wrapped selector and overlay list windows in ScrollView for proportional right-edge scrollbars.
- Dropped numeric position/count footers in favor of the scrollbar.
- Simplified SelectList status line to search hints only.
- Added ED3-risk autocomplete repaint test for POSIX terminals.
- Removed async image-link materialization between user message_start and addMessageToChat.
- Fixed steering bubbles rendering below the tool output they were sent to steer.
- Materialized clickable image links via synchronous blob-store fallback instead.
- Cleared native scrollback on `omp`/`omp -c` so the resumed transcript no longer stacks on the prior run's welcome screen.
- Tracked assistant block finalization so aborted streaming messages stay repaintable when status rows land beneath them on ED3-risk terminals.
- Added image-reference rendering to make `[Image #N]` placeholders clickable in chat.
- Added MIME-aware image blob materialization with extensioned sidecar paths.
- Added clickable path, line, and URL hyperlinks for read, search, and fetch outputs.
- Hardened OSC8 hyperlink emission with URI validation and control-byte/idempotency checks.
- Replaced bottom-most-block liveness with a finalization check so the live region spans every still-mutating block.
- Kept unfinalized tools repaintable when out-of-band inserts append finalized blocks below them.
- Recomputed blocks as they cross out of the live region to seal their final content.
- Added `NativeScrollbackLiveRegion` seam so components report the live suffix start.
- Stopped ED3-risk streaming from dropping sealed transcript rows above the live block.
- Appended newly sealed rows once while keeping the active tail deferred to checkpoint.
The session-tree selector collapsed to "No entries found" whenever the
default filter rejected every entry. On a fresh session that is the
normal case: `sdk.ts` writes `model_change` + `thinking_level_change`
at startup so model + thinking state survive resumes, and the default
filter treats both as bookkeeping. `selector-controller.showTreeSelector`
guards on `tree.length === 0` so the selector still opens, and the user
sees an unexplained empty panel with `(0/0)` next to a "Recent sessions"
list that does contain data.
Split the empty-state branch into three shapes:
- `flatNodes.length === 0` → unchanged "No entries found".
- `searchQuery` non-empty → "No entries match search \"…\"" plus a
Backspace hint, with the real total in `(0/N)`.
- otherwise → "N entries hidden by the current filter [mode]" plus
"Press Alt+A to show all, Alt+D for default", with the real total in
`(0/N)`.
So the fresh-session case now explains why the panel is empty and how
to widen it instead of reading as "/tree is broken".
Fixes#1909
- Added NativeScrollbackLiveRegion seam reporting where a component's transient suffix begins.
- Pinned the live block and chrome below it out of native history during foreground streams on ED3-risk terminals.
- Consumed pending forced scrollback wipes while pinned to avoid yanking a scrolled-up reader (#1682).
- Tracked the previous live child in TranscriptContainer and forced a one-off recompute when a block leaves live status.
- Skipped snapshot reuse for that transitioning block so coalesced finalize-and-append frames seal transcript blocks at their final content.
- Added a regression test covering the stale-prefix freeze case on ED3-risk terminals and confirming the frozen block stays unchanged until thaw.
- Adjusted session and dashboard renderers to derive heights from live terminal rows.
- Propagated terminal-row callbacks through picker/controller wiring and session selectors.
- Reworked list visibility and page navigation to honor row-based budgets and footer lines.
- Added DECRQM 2031 startup probing and stopped OSC11 polling once support was confirmed.
- Added token-aware query matching so highlights mirror `HistoryStorage.search` tokenization.
- Added token highlighting, compact relative timestamps, and selected-row styling in results.
- Added PageUp/PageDown and Home/End selection shortcuts in `HistorySearchComponent`.
- Added selector matchers for `tui.select.pageUp` and `tui.select.pageDown`.
- Changed empty-result messaging to distinguish `No history yet` from `No matching history`.
- Added tests for page/home/end navigation and token-highlighting result rendering.
- Added assistant-message completion state and stable-line count reporting.
- Added transcript stable-row aggregation and snapshot replay to keep unstable rows out of scrollback.
- Added TUI stable scrollback boundary APIs and stable-prefix commit path.
- Added regression tests proving unstable rows stay out of scrollback until stabilized.
Marketplace plugin toggles in Settings → Plugins wrote the installed-plugin
registry and then only requested a render through the settings callback. In a
live TUI session that left already-loaded slash commands, hooks, tools, agents,
and SSH tool state unchanged until the user manually reloaded plugins or
restarted.
Make the plugin-change callback awaitable and wire the settings selector to the
same reload pipeline used by the slash-command runtime: clear plugin-root caches
for the active project registry, refresh slash command state, refresh the SSH
tool, then request a render. Await the callback after npm and marketplace
registry writes so Settings → Plugins reflects live plugin state immediately.
Add a regression test proving a marketplace toggle calls setPluginEnabled before
the plugin-change reload callback resolves.
`MarketplacePluginDetailComponent` rendered the raw `installPath` from
the installed-plugin registry, which leaks the user's home directory
into the TUI when the plugin lives under `~/.omp/cache`. Route it
through `shortenPath` so $HOME becomes `~` before the value reaches
`Text`, matching the repo's TUI sanitization rules (per review on #1844).
`PluginSettingsComponent.#showPluginList()` only inspected the npm plugin
registry, so the TUI's `Settings → Plugins` panel rendered "No plugins
installed" whenever the user had no npm plugins — even when many
marketplace plugins were installed. The `/plugins list` slash command,
`omp plugin list` CLI, and the install/uninstall selectors already
merged `PluginManager.list()` with `MarketplaceManager.listInstalledPlugins()`;
the settings panel was the only surface that missed the marketplace
registry when it was added.
Extend the panel to consume both data sources:
- Replace `PluginListComponent`'s `InstalledPlugin[]` input with a tagged
union `PluginListEntry = { kind: "npm"; plugin: InstalledPlugin } | { kind:
"marketplace"; plugin: InstalledPluginSummary }`. Each row now carries an
`[npm]`/`[marketplace]` kind badge, a scope tag, and the shadow indicator
for user installs overridden by a project entry. Widen the SelectList
primary column so long `name@marketplace` ids stay readable.
- Add `MarketplacePluginDetailComponent`: single `Enabled` toggle plus the
read-only `InstalledPluginEntry` metadata (version, install path,
installed-at, last-updated, git commit SHA). The toggle calls
`MarketplaceManager.setPluginEnabled(pluginId, enabled, scope)` — same
path `/plugins enable|disable` uses.
- Update `PluginSettingsComponent` to await both `PluginManager.list()` and
`MarketplaceManager.listInstalledPlugins()` in parallel, build the merged
list, and route selection to the kind-specific detail view. The empty
state now lists both install commands (npm and marketplace).
Fixes#1842
- Added TranscriptContainer that snapshots non-live blocks to avoid stale scrollback duplicates.
- Thawed snapshots at prompt-submit checkpoints for reconciliation.
- Repainted eager streaming tail on overflowing shrink to unfreeze UI (issue #1682).
- Classified each session's final message as done, interrupted, aborted, error, or pending from a 32 KiB tail read.
- Rendered the status as a colored segment on the session metadata line.
- Added `peekFileTail` and `readTextSuffix` across storage backends to read file tails in one pass.
- Simplified `MemorySessionStorage` to a string array mirror with a sidecar mtime map.
- Updated completion and ask notifications to pass structured payloads.
- Updated completion and ask notifications to include explicit message metadata fields.
- Adjusted abort-guard and retry-capability tests for the new notification/options behavior.
- Enabled resume picker to preload sessions and toggle folder/all scope with Tab.
- Enabled resume flow to fall back to all-project sessions and switch cwd on resume.
- Added centralized applyCwdChange to refresh caches, commands, and UI after cwd updates.
- Updated session restoration to adopt restored session cwd and sessionDir when present.
Filtered the logout selector to credentials that /logout can actually remove and reported ambient env/config auth when direct logout cannot clear it. Added selector coverage for env-only OpenCode providers.\n\nFixes #1658
Enable eager native scrollback rebuild mode while assistant text is actively streaming so reflowed Markdown rows do not leave stale duplicated tails in WSL/Windows Terminal scrollback.\n\nFixes #1615