- 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.
- Updated read-group rendering to use the enabled success mark and omitted duplicate success marks on child files in grouped reads.
- Adjusted find and search renderers to apply tool-title coloring, search icons, and padded layout via createCachedComponent.
- Added tests covering read-group success marking and padded find/search renderer output.
- Updated task call and result rendering to process shared context with the Markdown renderer, so context sections are now displayed with proper Markdown formatting.
- Stopped shimmer animation on pending bash/eval/task blocks once async state is `running`, preventing the committed frame from freezing a transient dark border segment.
- Adjusted rule path display to fall back to a root-relative path when cwd-relative resolution is unavailable.
- Replaced approved-plan renaming with `resolveApprovedPlan` resolution and state/slug lookup.
- Updated ACP and interactive apply flows to propagate canonical `planFilePath` instead of renamed paths.
- Added local plan fallback lookup by mtime for unresolved slugs after plan approval.
- Restricted plan-mode writes to `local://` plan artifacts and simplified path handling.
- Added archive format sniffing to identify ZIP, TAR, and TAR.GZ from file bytes.
- Added MIME/extension and header-based routing for notebook, sqlite, and archive payloads.
- Added archive entry rendering with slash-terminated dirs and size suffixes.
- Added tests for archive, sqlite, notebook, and fallback binary dispatch scenarios.
- Collapsed non-touched phases to one-line summaries in multi-phase todo renders while retaining full output for active, touched, or expanded views.
- Computed touched phases from in-progress tasks, completion transitions, and tool operations, with init operations now marking all phases.
- Added renderer tests covering collapsed rendering, argument-less fallback behavior, expanded mode, and separator-free phase output.
- Replaced the inline todo-phase preview loop in todoToolRenderer with renderTreeList.
- Kept task output generation delegated through formatTodoLine while passing expanded state and preview limits to the shared helper.
- 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.
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
- 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.
- 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.
- 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.
- 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.
- 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.
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
- 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 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.
- Adjusted renderCollapsedSearchGroups to compact each result group before truncation so first-section hits stay visible.
- Removed collapsed-body truncation notices and kept truncation status in the output header.
- Made PI_INTENT_TRACING, PI_AUTO_QA, PI_PY, and PI_JS take precedence when set.
- Fell back to config when the env flag is unset instead of ORing.
- Surfaced PI_PY=0/PI_JS=0 in the disabled-backend error messages.
- Updated write streaming content formatting to accept an expanded flag and show full output only when expansion is active.
- Passed the expanded state from the write renderer so in-flight write previews now lift the 12-line cap on Ctrl+O.
- Added streaming write preview tests to verify collapsed tail capping, expansion growth, and short-write behavior.
- Replaced `¶path#hash` prefix with `[path#hash]` delimiters across parser, tokenizer, and grammar.
- Updated prompts, docs, and recovery paths to the new bracketed form.
- Stopped expanding the volatile tool block so a >100-line code arg no longer overflows the viewport.
- Kept streaming and resolved render shapes consistent at codeMaxLines.
- Added timeout pause/resume control ops and helper to suspend idle timers during bridge work.
- Fixed TimeoutError on long delegated agent()/llm() calls by pausing timeout while silent.
- Updated IdleTimeout with reference-counted pauses, ignored checks while paused, and resumed fresh.
- Replaced heartbeat keepalives with timeout-control events in bridge paths and status routing.
- Described "auto" default gating MCP tools past 40-tool threshold.
- Noted late resolution in createAgentSession after registry exists.
- Updated legacy mcp.discoveryMode mapping to MCP-only.
- Made "auto" the default, hiding MCP tools past 40-tool threshold.
- Centralized discovery mode resolution in shared mode helper.
- Activated search tool in createAgentSession once full registry exists.
- 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.
The no-selector run_watch guard was using resolveDefaultRepoMemoized via tryResolveCurrentRepo, so a long-lived process could validate against a stale cwd-to-repo cache entry after the checkout or GitHub remote at that path changed. That allowed the guard to trust the current HEAD for an explicit repo based on the old cached repository.
Add a fresh best-effort cwd repo lookup for safety checks and use it before deriving branch/HEAD. Cached lookup remains for search default scoping where stale data only affects a convenience fallback. Added a regression test that populates the cache, changes the mocked repo at the same cwd, and asserts run_watch rejects before issuing API calls.
Refs #1949#1951
resolveGitHubRepo rejected calls that supplied both an explicit repo and a full Actions run URL when the two owner/repo slugs differed only by casing. GitHub repository paths are case-insensitive, so this was the same class of false mismatch as the cwd guard fixed earlier.
Compare repo slugs through a shared ASCII case-insensitive helper and use it for both the run-URL consistency check and the cwd guard. Added a regression test for repo=cagedbird043/cxf with a run URL under CagedBird043/CXF.
Refs #1949#1951
GitHub owner/repo slugs are case-insensitive; `gh repo view` returns
the canonical casing while callers may pass any casing. The new guard
used strict equality, so a caller in the correct repo who typed
`owner/repo` while the canonical form was `Owner/Repo` was forced to
pass a redundant `branch`/`run` selector. Normalize both sides via
toLowerCase() before deciding the cwd is a different repository.
Regression test covers the casing-only match.
Refs #1949#1951
executeRunWatch passed undefined for the explicit `repo` to
resolveGitHubRepo, so a call like
`{op: "run_watch", repo: "owner/cxf", branch: "main"}` from a nested
or umbrella workspace silently fell through to `gh repo view` in cwd
and streamed `watching <sha> on <cwd-repo>` against the wrong
repository.
Route params.repo through resolveGitHubRepo so the explicit owner/repo
wins over both cwd inference and run-URL inference. When no `branch`
or `run` selector is given, refuse to derive the watched commit from
`git HEAD` unless the cwd actually points at the resolved repo —
otherwise raise a ToolError telling the caller to pass `branch` or
`run` instead of silently rebinding to an unrelated commit.
Also deduped resolveSearchRepoScope's best-effort cwd resolution into a
shared tryResolveCurrentRepo helper used by the new guard.
Fixes#1949
- Parsed zip metadata via central directory and lazy ranged reads.
- Inflated member contents only when a specific entry is read.
- Prevented large or corrupt zips from freezing directory reads.
- Added selectorLineRanges to extract ranges from raw/conflicts selectors.
- Routed internal URLs through URL-aware splitter in content search.
- Treated display-mode selectors as whole-resource searches instead of rejecting.
AgentSession now stores the same scoped AsyncJobManager reference that tools receive: owning top-level sessions use their constructed manager, subagents inherit the parent's manager, and secondary in-process top-level sessions get no manager when a singleton is already live.
getAsyncJobSnapshot and ACP delivery drains now use that scoped manager instead of AsyncJobManager.instance(), so secondary sessions cannot report or drain the primary session's background jobs. The regression test covers a secondary session created while the primary has a Main-owned running job.
Per PR review on #1926: a secondary in-process top-level createAgentSession() that exposes bash/task/job tools would still call AsyncJobManager.instance() at execute time, register on the primary's manager, and have the primary's onJobComplete enqueue results into the primary's yieldQueue — corrupting the owning session's conversation.
ToolSession now carries an asyncJobManager reference scoped to its session: the constructed manager for top-level sessions, the inherited singleton for subagents (so their bash/task completions still flow into the spawning conversation as before), and undefined for secondary in-process top-level sessions that found a singleton already installed. bash, task, and job tools resolve the manager through ToolSession instead of the process-global singleton, so a secondary session whose tools attempt async work fails fast with the standard "Async job manager unavailable" error instead of contaminating the primary.
Mid-session edits to hindsight.bankId / bankIdPrefix / scoping kept the
active HindsightSessionState pinned to the bank selected at session
start, so retain/recall/reflect calls landed in the stale bank. Settings
hooks now fire onHindsightScopeChanged; the backend rebuilds the
primary state against the recomputed scope, disposing the previous one
after flushing its queue so queued tool-initiated retains still land in
the bank they were enqueued for.
Also:
- Renamed ensureBankMission to ensureBankExists. The old version
skipped creation entirely when bankMission was blank, so the first
mental-model POST (auto-seed) could land against a never-PUT bank.
Bank creation is now idempotent and unconditional, and runs before
mental-model bootstrap.
- Fixed AgentSession.dispose to flush the retain queue BEFORE clearing
the session state pointer. Reversed, HindsightRetainQueue.#doFlush's
identity guard would see the cleared pointer and drop the spliced
batch with a 'session vanished' warning.
- Snapshotted hindsightScopeCallbacks before iterating because each
rebuild subscribes a fresh callback inside the same fire; iterating
the live Set would spin.
Fixes#1902
Handled omp://docs as an embedded documentation search root alongside omp://.
Added regression coverage for searching embedded docs through the docs alias.
Fixes#1898