- Added `selectionMarker`, `checkedIndices`, and `markableCount` options to render radio/checkbox glyphs per row.
- Moved checkbox rendering from inline label prefixes into the selector component.
- Kept trailing control rows like "Other"/"Done" on the plain cursor.
- Added `isReadOnlyAgent` and `READ_ONLY_TOOL_NAMES` to classify agents.
- Marked read-only agents and forbade edits, commands, and reasoning offload.
- Added tests for capability classification and description rendering.
The `search` tool required `paths` via a strict `union([string,
array.min(1)])`, so any call that omitted `paths` (or passed an empty
array) was rejected at schema validation with `paths: Invalid input`
and never ran — turning a recoverable "no scope given" into a fatal
tool-call failure.
Make `paths` optional and default an omitted/empty value to the
workspace root (`.`), matching the documented prompt contract. Behavior
is unchanged when paths are supplied. Adds regression coverage for the
omitted and empty-array cases.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Renamed `TodoWriteTool` to `TodoTool` and its source/prompt files.
- Updated tool registration, schema, renderers, and gating to `todo`.
- Adjusted cursor provider native tool names and tests to match.
- Renamed strike-animation constants and `todo-error-reminder` type.
- Extended line selector parsing in path-utils to accept `..` as a forgiving alias for `-`, with `..` normalized during chunk parsing.
- Updated selector-matching regexes for file selectors and internal URL selectors to recognize alias-style ranges in single chunks and comma-separated lists.
- Added tests covering `N..M`, `N..`, mixed separators, inverted-range errors, and path-splitting behavior with `:N..M` selectors and `foo:../bar.ts` paths.
- 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.
- Rendered single-choice questions with circular radio glyphs instead of checkboxes.
- Kept rectangular checkboxes for multi-select questions.
- Added radio.selected/unselected symbols to unicode, nerd-font, and ASCII presets.
Surface the hidden discoverable built-in tool names (write, find, search, lsp, task, ...) in the search_tool_bm25 description when tools.discoveryMode is "all", so a model can form a targeted BM25 query by name instead of guessing or falling back to shell. mcp-only mode is unchanged (no built-ins advertised) and the total-tools count still includes them.
- Expanded path parsing to split top-level comma, semicolon, and whitespace entries.
- Updated find/search and scope resolution to apply delimiter expansion before path-spec validation.
- Updated read tool fallback to try split path parts before raising missing-path errors.
- Coerced bare string arguments into singleton arrays for array-typed schemas.
ExaProvider.isAvailable() and searchExa() now consult AuthStorage so Exa credentials configured through the broker/credential store work alongside EXA_API_KEY, matching the other API-key search providers.
Refs #1695
Replace the sunset V0 Search API with V1 (POST /api/v1/search) under the
existing `kagi` provider id instead of shipping a parallel `kagi-v1`
provider. Credentials still resolve through the shared AuthStorage broker
(Bearer token, KAGI_API_KEY, /login kagi), and recency now maps to a
UTC-deterministic filters.after date.
- Merge V1 client into src/web/kagi.ts (categorized result buckets, direct
answer, related/adjacent questions)
- Keep classifyProviderHttpError mapping for auth/quota signals
- Drop the kagi-v1 entries from the provider registry, order, type union,
and settings schema
- Consolidate tests into web-search-kagi.test.ts
- Added ROW_COUNT_PROBE_CAP to limit rows scanned when counting tables, preventing JS thread freezes on large databases.
- Used sqlite_stat1 estimates for tables exceeding the cap; exact counts only for provably small tables.
- Introduced TableRowCount type with exact/estimate/atLeast variants reflected in rendered output.
- Added `DiagnosticsLedger` to track diagnostics already surfaced per file, suppressing repeats within a session.
- Wired dedup into both edit and write tools via a `transformDiagnostics` hook on the writethrough pipeline.
- Added `lsp.diagnosticsDeduplicate` setting (default: true) to control the behavior.
- Only bridge heartbeats (`agent()`/`llm()`) now re-arm the watchdog; compute, stdout, `log()`/`phase()`, and ordinary tool calls count against the budget.
- Emitted an immediate heartbeat at bridge call start to avoid early abort near budget edge.
- Removed `idle` flag and "of inactivity" suffix from timeout annotation strings.
- Updated docs, prompts, and comments to reflect the new wall-clock semantics.
Guarded find renderer path summaries so raw pre-validation string paths render instead of throwing. Added coverage for pending, fallback, empty, and detailed result render paths.\n\nFixes #1622
- Added `repairDoubleEncodedJsonString` to unescape fields double-encoded by the model (e.g. literal `\n`, `\"`, `\uXXXX` in `context`/`assignment`/`description`).
- Scoped repair to natural-language fields only, leaving code-bearing tools untouched.
- Applied repair on both render and execution paths in `TaskTool`.
Send the LSP exit notification after a successful shutdown response before falling back to process termination. Add a regression test that fails when a server receives shutdown but not exit.\n\nFixes #1593
- Added `!streamedReplayUnsafeContent` guard to `canRetryProviderFailure` to avoid replaying unsafe content on retry.
- Updated test fixtures to supply a required `workspaceTree` parameter via a shared `emptyWorkspaceTree` helper.
- Added optional `onStatus` callback wiring across eval backends and JS/Python executors for live status streams.
- Added collectDisplay-based forwarding so `emitStatus` and `onDisplay` route status outputs consistently.
- Expanded agent status payloads with preview/model/token-cost context and kept completion updates single-pass.
- Added status upsert and render adjustments in `tools/eval.ts` to coalesce agent events with progress stats.
- Added status/progress test coverage for running/completed agent events, final metric retention, and parallel placement.
- Updated CHANGELOG Unreleased notes to record live progress updates and completion-status metric fixes.
- Replaced ad-hoc ANSI/VT stripping regexes with `stripVTControlCharacters` in status text handling and related tests.
- Updated status footer rendering to truncate using `truncateToWidth` and visible width after VT stripping.
- Extended tui cursor handling and rendering to strip markers from all lines and fit repaint/append-tail lines to width.
- Expanded deterministic render tests with overlay-aware assertions and recorded the truncation/cursor-marker behavior in changelogs.
F1 (coding-agent): close the withFileLock mkdir-vs-writeLockInfo race that
let a losing contender wipe the winner's freshly-created lock directory.
Every lock now carries a per-process UUID token; releaseLock verifies the
token before fs.rm, and isLockStale no longer treats an info-less but
fresh dir (or a dir that vanished mid-check) as stale.
F4 (coding-agent): sanitize tabs and truncate oversized error strings in
formatErrorMessage so error renderings that embed file content
(apply_patch, hashline, etc.) cannot break terminal alignment or
overflow the line width.
F7 (ai): support named-tool routing on Google providers. Widens
GoogleSharedStreamOptions.toolChoice and GoogleGeminiCliOptions.toolChoice
to accept { mode: 'ANY'; allowedFunctionNames }. mapGoogleToolChoice
now converts ToolChoice { type: 'tool'|'function', name } to the wire
shape (mirroring mapAnthropicToolChoice). buildGoogleGenerateContentParams
and the gemini-cli request serializer honor the allow-list.
- Updated the internal URL resolution test input pattern to use a new search phrase.
- Updated the expected assertion string to match the revised phrase in command output.
- Expanded search scope handling for virtual multi-file targets and executed grep only when searchable paths existed.
- Merged `searchVirtualResources` results into main output and rendered internal URL matches as accent lines.
- Updated grouped-file output to detect URL-like paths and keep full URL headers for root grouping.
- Documented URL path/range behavior and added tests for doc routing, missing-content errors, and `omp://` expansion.
- Added virtual internal URL path resolution in `SearchTool` via `InternalUrlRouter` for in-memory search.
- Added `omp://` root expansion so `search` resolves and scans each completion target.
- Fixed `SearchTool` handling of internal URLs without `sourcePath` by returning virtual matches instead of `Path not found`.
- Extended `edit-renderer.test.ts` coverage for normalizing raw streamed text in custom text renderers.
- Added helper logic to treat raw non-JSON `__partialJson` values as edit `input` for hashline and apply_patch args.
- Updated edit argument preparation, preview generation, and streaming fallback rendering to use that derived input.
- Added renderer tests verifying raw hashline and apply_patch partial streams render target paths and patch content.
- Updated hashline preview diffing to route section edits through shared apply/resolve logic and partial streaming parsing.
- Allowed previews to accept live content-hash matches immediately when snapshot records are missing.
- Enabled stale-tag recovery from the snapshot store for anchor-scoped edits and added coverage for snapshot-capture behavior and session-mismatch failures.
- Added clockwise sweeping dark segment animation to output block borders while bash/eval tool calls are pending/running.
- Changed bash renderCall to immediately render a full bordered block instead of a one-liner status preview, so silent commands show the framed block for their entire runtime.
- Added shimmerEnabled() helper and wired animate flag through OutputBlockOptions, CodeCellOptions, and shell/eval renderers.
- Added todo_write strike-frame animation timing and updated execution flow after completion finalizes.
- Added strike animation cancellation in cleanup to clear todo timer and reset frames when spinner is idle.
- Removed todo-closing state and timeout handling from interactive mode and simplified empty todo-list rendering.
- Reworked todo-write to compute completion transitions, track completedTasks, and render strike-through frames.
- Added test coverage for completedTasks, theme setup, and strike-through progression at hold-frame thresholds.
- Tagged non-zero bash command completions as error results, capturing `exitCode` and keeping exit notices in returned text.
- Updated the shell renderer to hide duplicate exit notices from output while surfacing failed command status in the footer.
- Added tests for non-zero versus zero-exit bash results and footer rendering of failed commands.
- Added shared helpers and inline TUI renderers for retain, recall, and reflect tool outputs.
- Added tool registry entries for retain, recall, and reflect to use the new inline renderers.
- Updated changelog notes describing new memory inline rendering semantics and output headers.
- Added memory renderer tests for summary, truncation, streaming, and expand/collapse behavior.
- Updated the edit preview coalescing key to include streaming state plus a hash so final non-streaming diffs are not skipped when payload bytes match.
- Used a hashed partial-stream key as fallback when tool args are not JSON-serializable, keeping deterministic dedup cache keys.
- Added a regression test that verifies single-line hashline streaming edits render the completed preview diff instead of "No changes would be made".
- Preserved Alt and Ctrl+Alt letter ESC-prefix matching when kitty_protocol_active is true to support mixed tmux and Kitty keyboard modes.
- Parsed two-byte ESC sequences before legacy sequence lookup so mixed-mode Meta pairs are treated as Alt letter keys instead of legacy aliases.
- Updated native and TUI key tests to verify Alt+letter and Alt+Shift+letter parsing and matching while enhanced mode is active.
Fixes#1511
- Replaced snapshot internals with full-file records and removed contiguous/sparse snapshot APIs.
- Added file-hash normalization, computed `computeFileHash`, and updated grammar/messages to 4-hex tags.
- Simplified recovery by checking whole-file hashes first, then applying merge-replay fallback after mismatches.
- Updated coding-agent tools to use `record`/`recordFileSnapshot` and skip hash headers for unsnapshotted large files.
- Expanded patcher and snapshot tests to verify 4-hex anchors, hash deduplication, and cache-capped behavior.
Four refinements to the sticky Todos panel on top of the live SessionObserverRegistry linkage:
- Cube animates whenever any visible open todo is "live" (in_progress, or a still-pending todo with a matching in-flight subagent). The previous subagent-only gate left lone in_progress rows on the static '⟳' fallback; ticking on an orphan in_progress row is the correct "still open" signal.
- 'normalizeForTodoMatch' now collapses any non-alphanumeric run to one space, so subagent descriptions with '#', '.', ':' etc. match todo content that omits the punctuation. Fixes the case where 3 subagents were spawned but only 2 of 3 matching todos lit up because the matcher's normalizer collapsed whitespace but left '#' intact.
- New '#reconcileTodosWithSubagents' runs on every observer-registry change and auto-checkmarks any pending/in_progress todo whose content matches a 'status === "completed"' subagent description. Failed/aborted subagents intentionally don't auto-flip - those stay open for the user (or next agent turn) to decide.
- All-done close animation: when every visible task is closed, fold the panel away over ~1.4s. A 900ms celebratory frame holds the bright bold "Todos ✓" header so the user can read the final checkmarks, then a fade through 'muted' / 'dim' with rows progressively dropped from the bottom. '#todoClosingState' state machine plays the animation exactly once per open->all-closed transition and aborts cleanly if a new open task arrives mid-animation.
Verification:
bun test test/tools/todo-write.test.ts → 24 pass / 0 fail (one new case for # punctuation tolerance)
bun run check → biome + tsgo clean
The always-on Todos panel above the editor pinned to the first 5 tasks of the active phase, so each todo_write flip mutated at most one row (color + strikethrough) and the +N more hint only shrank at end-of-phase. Marking task 1 done left tasks 6,7,... invisible until tasks 1-5 were all closed.
Introduce selectStickyTodoWindow(tasks, maxVisible=5) — returns up to 5 open (pending / in_progress) tasks in original phase order plus the count of remaining open tasks for +N more. When every task is closed, falls back to the trailing window (with +N more suppressed) so the panel keeps useful context until getActivePhase walks to the next phase. The collapsed branch of #renderTodoList now uses it; the expanded branch is untouched.