- Updated tool expand-hint rendering to use `expandKeyHint()`, which pulls the `app.tools.expand` binding and formats collapsed previews as `<key>: Expand`.
- Updated related tests in render utils and TUI regressions to assert the new hint string for default and remapped bindings.
- Added a resolve-tool regression test and changelog note covering `action: "discard"` with no pending action as a successful cancellation.
- Handled discard requests by returning a no-op success response when no action is pending.
- Kept apply requests on the same path to throw ToolError when nothing is pending.
- 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.
- Anchored each redraw at column 0 and terminated rows with CRLF instead of bare LF.
- Capped each line to terminal width so wrapping cannot desync the cursor-up.
- Threaded stdout/stderr columns into the progress sink.
- Replaced split-by-blank parsing in grouped renderers with classifyGroupedLines.
- Introduced path-tree grouping and folding to render multi-level directory headers.
- Normalized and deduplicated grouped paths, treating URL-like entries as root files.
- Adjusted file/url context mapping to keep line links stable across blank boundaries.
- Replaced `providers.parallelFetch` with a new `providers.fetch` enum in settings and added migration cleanup for the legacy key.
- Updated `renderHtmlToText` to follow configured reader preference with ordered fallback attempts and remote-reader timeout handling before local conversion.
- Updated YouTube and fetch tests to use `providers.fetch` and cover Jina-first stall fallback behavior.
- Enabled DEC 2026 for Alacritty/VS Code and via TERM_FEATURES Sy token.
- Stopped blanket-disabling SSH for recognized direct terminals.
- Made the DECRQM probe enable sync on a positive report, not just disable.
- Extracted synchronizedOutputUserOverride so opt-out beats force-on.
- Added PlanReviewBlock reporting append-only so an over-tall plan plus selector commits the scrolled-off head to native scrollback.
- Avoided top-clipping of long plans on ED3-risk terminals where a plain Container is deferred.
Used fs.stat to confirm delayed dlv Unix socket creation before connecting so Linux socket-mode adapters do not race Bun.connect. Added a delayed socket adapter regression test covering the launch path.\n\nFixes #2013
- ToolExecutionComponent was updated to skip append-only treatment for finalized blocks and pass result state into `isStreamingPreviewAppendOnly`.
- Eval rendering was changed to render full code continuously and to report append-only status only once a result exists, avoiding commitment of stale pending previews.
- Live-region tests were added for expanded eval output overflow and for append-only transitions from pending to finalized streaming states.
- Lazy-loaded OTEL SDK, HTML export, TTSR, and autoresearch modules.
- Made resolveMemoryBackend async to import backends on demand.
- Replaced backend resolution with direct settings reads for rekey checks.
- Migrated Effort and THINKING_EFFORTS imports to @oh-my-pi/pi-ai/effort in CLI args and launch command files.
- Split model-registry dependencies across focused @oh-my-pi/pi-ai submodules instead of the root barrel export.
- Deferred setup wizard import until setup was forced or version stale.
- Dynamically loaded ACP, RPC, and print mode runners only when used.
- Added a marketplace auto-update scheduler with off-mode early exit and non-blocking errors.
- Added setup-version assertions to keep CURRENT_SETUP_VERSION aligned with scenes.
- Added a WeakMap cache in compileEquivalenceConfig to reuse compiled configs.
- Raised QUALIFIED_NAMESPACE_SUFFIX_CACHE_CAP and HEURISTIC_CANDIDATES_CACHE_CAP from 256 to 4096.
- Reworked resolveCanonicalIdForModel to build officialMatches during candidate iteration.
- Added `isStreamingPreviewAppendOnly` to `ToolRenderer` for per-tool streaming mode selection.
- Updated `ToolExecutionComponent` to query append-only predicates only while a call preview is streaming.
- Marked expanded write previews as append-only so over-tall streaming output can commit head rows.
- Threaded resolved status-line `segmentOptions` into `#buildSegmentContext` construction.
- Added regression tests for scrollback retention and append-only state transitions.
- Reworked message parsing to process complete frames from a pending chunk queue.
- Added chunk-aware header scanning and range copy to avoid repeated buffer concatenation.
- Persisted partially read bytes in client.messageBuffer during reader teardown.
- Added Bun preload that records inclusive per-module windows and resolved static import edges via plugin hooks.
- Shared events through a dependency-free buffer so the preload and logger avoid importing each other.
- Rendered module spans as a body/TLA-ranked dependency tree, separating graph wait from top-level work.
- Back-folded captured load phase into the root window to shrink the opaque pre-instrumentation figure.
- Replaced WeakMap model cache with provider/id string keys for stable reuse.
- Returned official model ids directly when matched, before heuristics.
- Collapsed non-message token path to system prompt and tool schema totals.
- 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.
- Used `||` so empty stderr falls through to abortReason in agent bridge.
- Preferred assistant errorMessage over "Cancelled by caller" on internal aborts.
- Forced `maxRuntimeMs: 0` for eval subagents via ExecutorOptions override.
- Parsed /actions/runs URLs into run and job render handlers.
- Rendered run metadata with per-job breakdown, showing steps for failed jobs.
- Fetched job logs via API token, stripping ISO timestamp prefixes.
- 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.
The Anthropic-compat endpoints hosted under *.xiaomimimo.com (every
Xiaomi MiMo Token Plan region plus api.xiaomimimo.com) emit thinking
blocks without a signature. convertAnthropicMessages defaulted to
"signing capable" for any endpoint not explicitly allowlisted as
non-signing, so MiMo's unsigned thinking blocks were demoted to text on
every continuation request. Without its prior reasoning replayed, MiMo
destabilized tool-call argument serialization — the root cause behind
the args?.ops?.map crash already mitigated at the renderer in #2005.
Extend isNonSigningAnthropicEndpoint to cover the xiaomi catalog
provider, every xiaomi-token-plan-* provider id, and any baseUrl on
xiaomimimo.com so the existing non-signing replay branch fires for MiMo
the same way it does for DeepSeek and Z.AI.
Fixes#2005
Python eval agent() collapsed every subagent runtime-limit abort into a
generic 'RuntimeError: bridge call __agent__ failed' instead of the real
reason. runEvalAgent built its failure message with:
result.error ?? result.stderr ?? result.abortReason ?? <default>
? is nullish-coalescing, so result.stderr = "" (the executor's value for
a runtime-limit abort) short-circuited the chain and never reached
abortReason. The host bridge then shipped {ok: false, error: ""}, and
prelude.py's '<msg> or <fallback>' picked the named-bridge fallback.
Extracted buildSubagentFailureMessage(): aborted subagents prefer the
trimmed abortReason; otherwise fall through error, stderr (trimmed),
abortReason, and the named-bridge default. Empty/whitespace strings no
longer mask anything. The failure-detection condition also accepts
result.aborted so an abort with exitCode 0 (theoretically) still flows
the abort reason out.
Added a regression test asserting that runtime-limit aborts, whitespace
stderr/error, and totally blank aborts all produce non-empty messages
matching the executor's abortReason text.
Fixes#2006
- Forced authenticated ask requests to `experimental`, matching the anonymous fallback since the cookie session ignores pro upgrades.
- Kept TUI collapsed search answers full; capping now only applies in compact mode via `maxAnswerLines`.
- Preserved full multiline task pending preview instead of bounding it.
The todo tool's renderCall ran args?.ops?.map(...) directly, which throws
TypeError on any non-array ops value. parseStreamingJson surfaces such
shapes mid-stream: a partial Anthropic input_json_delta buffer like
'{"ops":"[{' becomes { ops: '[{' }, and intermediate states can hand back
null entries before object fields arrive. Each crash spammed Tool
renderer failed warnings and starved the TUI render loop.
Guard against:
- ops being any non-array (string, object, primitive)
- entries being null / non-object
- entry.items being a non-array
The fix is in the TUI renderer only — schema validation in the agent
loop is unchanged, so any genuinely malformed model output still
surfaces an invalid-args tool error to the model.
Fixes#2005
- Sent the OAuth token as `__Secure-next-auth.session-token` cookie since the ask endpoint ignores bearer headers and silently downgrades to `turbo`.
- Fell back to `result.title` when web results omit `name`.
- Renamed `callPerplexityOAuth` to `callPerplexityAsk` and removed a stray brace.
- Added tests covering OAuth, API-key, and anonymous request shapes.
- Stopped expanded view from dumping every match when all hits share one file.
- Applied an `EXPANDED_LINES × 2` budget while keeping context rows.
- Appended a `… N more matches` summary when truncated.
- 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.
- Stopped prepending system_prompt to the consumer ask endpoint, which lacks a system slot and refused the meta-instruction.
- Kept system_prompt as a proper system message on the API-key path.
- Updated `install:dev` to symlink `packages/coding-agent/scripts/dev-launch` into Bun's global bin directory as `omp`.
- Added a `dev-launch` shell script that launches Bun from an isolated directory and preserves the caller's working directory for restoration.
- Added a preload shim that restores `OMP_LAUNCH_CWD` before CLI execution so external project `bunfig.toml` preloads are not used.
- Added sanitizeErrorText in render-utils to normalize and truncate tool error messages.
- Introduced formatErrorDetail for indented subordinate error text without redundant icon or Error prefix.
- Updated goal and write tool renderers to use the new detail formatter, with write now handling isError results via a status header plus detail line.
- 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.