- Fixed edit/read/search/ast-edit/ast-grep outputs to resolve OSC8 links from session cwd.
- Fixed grouped-file output classification to honor headerBase and fileScope for parent path resolution.
- Fixed read and write renderers to use resolved source/resolved paths as hyperlink targets.
- Unified edit, ask, ast-edit, todo, write, and inspect outputs using framedBlock.
- Wrapped failure and warning cases in framed blocks with clearer status states.
- Standardized frame body rendering by trimming blank lines and clipping content width.
- Simplified tool execution layout by removing dynamic padding and background helpers.
- Added `icon.search` to theme symbol maps and used it for Search, Find, AST Grep, and BM25 success headers.
- Reworked `searchToolBm25Renderer` results into framed bullet lists with expand-item hints.
- Updated renderer tests to match the new search-tool output contract.
- Enabled call/result merging by setting mergeCallAndResult on TaskTool.
- Reworked task item lines into bullet lists and removed tree-style prefixes.
- Rendered task calls as framed blocks with isolated headers and pending status metadata.
- Changed result previews to hide task titles and `Tasks` headings when a result is present.
- Made `Component.invalidate` optional in `packages/tui/src/tui.ts` and callsites.
- Added `iconOverride` support to status-line rendering in `status-line.ts`.
- Added `borderColor` and `framedBlock()` primitives in `output-block.ts` for framed output styling.
- Adjusted `renderOutputBlock()` to draw a continuous border when no header text is present.
- Added terminal checkpoint-reconciliation tests in `submit-checkpoint-reconcile.test.ts` for pinned-tail behavior.
Prefer directory-capable adapters when selecting a launch adapter for a
resolved directory program. This keeps Go package directories on dlv in
mixed projects that also expose native-debugger root markers such as a
Makefile, instead of selecting gdb/lldb-dap first and rejecting the
directory during validation.
Added a regression test covering a Go module with both go.mod and
Makefile plus local dlv/gdb adapter shims.
Fixes#2020
The debug tool ran validateLaunchProgram before adapter selection and
rejected any directory program with `launch program resolves to a
directory`, while dlv's default `mode=debug` requires a Go package
path (a directory or .go source file). Every Go-module launch failed:
passing the module dir was rejected outright, and passing the compiled
binary failed at dlv with `not a valid go module`.
- Add `acceptsDirectoryProgram` to DapAdapterConfig/DapResolvedAdapter
and flag dlv in dap/defaults.json.
- In DebugTool.execute(launch), resolve the adapter first, then call
validateLaunchProgram with the resolved adapter — the directory
rejection only fires when the adapter does not advertise the flag.
- Add resolveLaunchOverrides in dap/config.ts: for dlv, derive `mode`
from the program shape (directory or .go file → debug; other file
→ exec). Plumbed through DapLaunchSessionOptions.extraLaunchArguments
and spread between adapter.launchDefaults and the hard-coded launch
fields in session.ts.
- Refresh tests: cover the no-dir-support adapter rejection, dlv on a
package directory keeping mode=debug, and dlv on a binary switching
to mode=exec.
Fixes#2020
- 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.
- Routed image-gen, inspect-image, and web search providers through `withAuth`.
- Used `reuseInitialApiKey`/`createAuthStorageResolver` for force-refresh and rotate retries.
- Attached HTTP status to thrown errors so the retry classifier detects retryable failures.
- 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 `ApiKeyResolver`/`ApiKey` types and exported auth-retry helpers.
- Changed stream and gateway auth retry handling to use resolver steps.
- Added initial-key, force-refresh, and rotate credential retries for auth failures.
- Updated agent and coding-agent integrations to use context-aware API-key resolvers.
- Added `AgentSession.freshSession()` to rotate provider-facing IDs and prune provider stream state.
- Added `/fresh` command handling in the builtin registry and mode command flow.
- Kept persisted session metadata intact during `/fresh` and cleared transient IDs on session switches.
- Invalidated `appendOnlyContext` and provider caches when refreshing provider state.
- 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.
- 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.
- 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.
- 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.
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.