- BLOCKING: reorder resolveProviderCredentialIdentityKey so email
identity takes priority over project — two users with different
emails on the same GCP project no longer get merged/hard-deleted.
- Added #getUsageReportScopeProjectId helper so Gemini CLI reports
(which set projectId on limit.scope but not metadata) still get
dedup coverage. Both metadata and scope projectId paths checked.
- formatAggregateAmount now falls back to limits.length when no
scope.accountId values are present, preserving pre-existing
behaviour for providers that don't set accountId on limits.
- Added 9 contract tests for the antigravity usage merge logic:
tier dedup, worst-fraction-wins, mixed-case collapsing,
reset-time-from-other-entry, windowId separation, metadata,
sort order, and null-on-no-project.
- Nits: label='Usage' (so formatLimitTitle renders 'Usage (Default)'
not bare 'Default'), id uses params.provider instead of hardcoded
string, tier field drops redundant ?? undefined.
Gemini CLI provider stores projectId on limit.scope but not in report
metadata, so the metadata-only projectId fallback added earlier missed
that case. Now all three lookup sites (dedup identifiers, TUI account
label, ACP account label) also check limit.scope.projectId.
- Antigravity usage provider now deduplicates model quota entries by tier
instead of emitting one bar per model (15+ redundant bars for one account).
The upstream API groups quota by tier — models within the same tier share
the same quota bucket, so per-model bars were misleading noise.
- Reports now carry credential email and accountId in metadata so the
/usage display and deduplicator can show meaningful account identities
instead of 'account 1'.
- formatAggregateAmount no longer uses limits.length as account count.
Instead counts unique accountId values from limit scopes — a single
account's N incomplete limits no longer display as 'N accts'.
- Usage report dedup now considers metadata.projectId for Google Cloud
providers so duplicate credential rows with the same project merge.
- account labels in both TUI and ACP markdown paths now fall back to
metadata.projectId before the generic 'account N' placeholder.
- Added anonymous Perplexity authentication mode for unauthenticated web searches.
- Switched web-search setup checks to use `isExplicitlyAvailable` and removed key enforcement in doctor.
- Updated Perplexity OAuth flow to reuse auth handling for all non-key searches and anonymous responses.
- Updated CLI and provider option help text to mark the Perplexity key optional with fallback.
- Showed answer text in full in the TUI; kept the `omp q` compact cap.
- Rendered each source as a single title/domain/age line with the URL linked on the title.
- Collapsed the metadata block to one Provider line plus Usage.
- Rendered search errors as a framed panel matching the success layout.
- Fixed custom-rendered tools with `mergeCallAndResult` (e.g. `lsp`) emitting a redundant tool-name line above the framed result.
- Collapsed the leading blank line for self-delimiting framed boxes.
- Added gallery fidelity routing `lsp`/`task` through the custom-tool branch via a `customRendered` fixture flag.
- Added gallery harness tests guarding state coverage and the custom-branch fallback label.
- 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.
- Added `setPaddingY` to `Box` and used `setBoxPaddingForFramedBlock` when rendering framed outputs.
- Read tool results now skipped vertical padding in framed blocks, removing extra blank rows above and below the output.
- Added a regression test for `ToolExecutionComponent` that confirmed framed read content no longer renders extra blank lines.
- 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.
- Updated rawTextInputFromPartialJson to stop excluding values that start with '[' from raw text fallback detection.
- Preserved existing exclusions for inputs starting with '{' and '"' in partial JSON detection.
- 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.
- Dimmed models whose context window is smaller than current usage.
- Skipped disabled entries during navigation and selection.
- Showed context-limit suffix and warning for unselectable models.
- 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.
- Fixed assistant transcript blocks to expose append-only commit-safe boundaries.
- Updated TUI live-region commit and pinned-paint logic to clamp commit-safe ends.
- Fixed long streamed assistant replies to remain in native scrollback on overflow.
- Added a persistent error banner so stream errors survive transcript scroll.
- Cleared the banner when the next turn starts.
- Skipped pinning for aborts and normal stops.
- 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.
Reserved the first wrapped plain-text login URL rows above the manual-code prompt, while rendering the complete wrapped URL again below the prompt for terminals without OSC 8 support.
Fixes#1919
Hoisted an always-visible OSC8 'Browser login' row in the setup sign-in tab so wizard body clipping never hides both the clickable link and the focused manual-code prompt. The wrappable URL text still renders below for terminals without OSC 8 support.
Fixes#1919
Rendered manual-code prompts before wrapped OAuth status lines so wizard body clipping cannot hide the focused input behind a long login URL.
Fixes#1919
Wrapped setup sign-in OAuth status lines instead of truncating them, and added a full OSC8 login link so narrow terminals still expose the complete URL.
Fixes#1919
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).
Logged structured session-title generation skip and failure outcomes with session/model context, and prevented credential lookup errors from escaping into the caller's swallowed promise path.
Added regression coverage for missing and failing title credentials.
Fixes#1892
- 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.
#requestAcpPlanApprovalChoice returned 'value !== REFINE_OPTION' which
treats any non-refine outcome — explicit dismissal, transport failure,
abort, or timeout — as approval. That meant closing the elicitation
dialog (or the request failing) granted the agent write access without
explicit user consent.
Tighten to 'value === APPROVE_OPTION' so only the explicit approve
selection passes the gate. Refine, dismissal, and every other outcome
fall through to refine semantics: the caller keeps plan mode active and
returns guidance text instead of renaming the plan and exiting.
Adds a regression test that drives a form-capable harness with a
cancelled elicitation and asserts the plan file is preserved, plan
mode/handler stay active, plan reference stays unset, and no mode-exit
notifications are emitted.
- Removed the AssistantMessageComponent completion flag and its stable-line counting helpers.
- Added a TUI regression test validating that reflowed streaming rows leaving the viewport are preserved in native scrollback and remain reachable.
- Removed changelog notes for obsolete stable-prefix scrollback APIs.
- Marked steering user messages and wrapped them pre-LLM so the model sees a `` envelope.
- Kept transcripts and persisted history with the user's original raw text.
- Restored `AssistantMessageComponent` stable-prefix completion API.
ACP plan approval exited plan mode internally and emitted the current-mode
notification, but it did not push the matching mode config-option update.
Clients that cache or render the config selector could therefore keep
showing mode=plan after approval switched the session back to default.
The approval path now emits the same config_option_update used by other
mode transitions, and the regression test asserts that the approval-driven
exit updates both current_mode_update and the mode config option.
ACP plan mode set the plan-mode state but never installed the standing
resolve handler that interactive mode wires in #enterPlanMode. The agent
in plan mode dutifully called resolve { action: 'apply', extra.title }
to submit its plan; ResolveTool.execute then consulted
peekQueueInvoker() ?? peekStandingResolveHandler(), found neither, and
threw 'No pending action to resolve. Nothing to apply or discard.' —
stranding the agent with no path out of plan mode in Zed (and any other
ACP client).
#applyModeChange now registers a standing handler when entering
mode: 'plan' and clears it when leaving. The handler:
- validates the plan file exists at the configured '/data/workspaces/can1357__oh-my-pi__1869/.omp-session/2026-06-04T15-12-15-302Z_019e9331-31c6-7000-9bce-6be119505a1d/local' path,
- normalizes the agent-supplied title to a safe filename stem,
- asks the ACP client to confirm via unstable_createElicitation when
the client advertises elicitation.form (auto-approves otherwise so
the agent never gets stuck on a client without the surface),
- renames the plan to '/data/workspaces/can1357__oh-my-pi__1869/.omp-session/2026-06-04T15-12-15-302Z_019e9331-31c6-7000-9bce-6be119505a1d/local/<title>.md,'
- sets the plan reference path so the next turn injects the plan as
context, then clears the standing handler + plan-mode state and
emits current_mode_update so the client UI reflects the exit.
Refinement (user picks 'Refine plan') returns guidance text and leaves
plan mode active so the agent can iterate.
Fixes#1869
- Registered and triggered a session-switch reconciler during init and after switch.
- Rebuilt resume flow to restore plan/goal mode state and clear stale mode flags.
- Marked fallback and context-promotion model switches ephemeral and skipped them on restore.
- Added regression tests for temporary model ordering, fallback precedence, and mode cleanup.
- Mapped left/right arrows to switch tabs in the extension dashboard.
- Updated agent and extension dashboard footers to show arrow controls.
- Reformatted HTTP transport assignment and reordered an import.
- Mapped the right arrow key to advance tabs in the agent dashboard.
- Mapped the left arrow key to reverse tabs alongside shift+tab.
- Kept existing tab and shift+tab handling intact for backward-compatible navigation.
- 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.
- Replaced the single-line description Input with Editor in agent-dashboard.ts for multiline entry.
- Added Enter-newline and Ctrl+Enter submit handling to the create-agent editor flow.
- Updated agent-creation-architect.md guidance for concise single-sentence whenToUse output.
- Added integration tests for multiline editor rendering and Ctrl+Enter submission.