- Changed bash interceptor configuration from boolean flags to customizable pattern-based rules array.
- Clarified hashline range replace semantics: end parameter is now strictly exclusive boundary.
- Fixed bash interceptor to apply built-in default rules when no custom patterns are configured.
- Updated hashline range validation and calculations to enforce exclusive end semantics throughout.
- Added renderInlineMarkdown() utility function to support inline markdown rendering with optional base color styling.
- Refactored ask tool to render questions and option labels with markdown formatting for improved text styling.
- Updated hook-input and hook-selector components to render titles as markdown with theme-aware styling.
- Implemented recursive token processing for nested markdown elements including bold, italic, code, links, and strikethrough.
Fixes#491
- Fixed rate-limit-utils to recognize and classify 'usage limit' errors as QUOTA_EXHAUSTED instead of transient.
- Added isUsageLimitError() utility function for unified detection of persistent quota limit errors across providers.
- Fixed Codex provider to return immediately on usage-limit errors instead of retrying, preventing unnecessary 5-minute delays.
- Removed usage.?limit pattern from TRANSIENT_MESSAGE_PATTERN to prevent misclassification of persistent quota errors.
- Added ACP (Agent Client Protocol) mode for headless agent operation via --mode acp flag.
- Integrated Agent Client Protocol SDK with session management, streaming communication, and event mapping.
- Added ensureOnDisk() method to SessionManager for immediate session persistence without requiring assistant messages.
- Changed session persistence to use atomic file rewrite for unflushed sessions.
- Implemented AcpAgent class with session management, prompt handling, MCP server configuration, and event streaming.
- Restructured model policy application logic to improve readability and reduce nesting.
- Extracted model override application into dedicated function calls for consistency.
- Added auto-reconnect capability for MCP servers with SSE stream monitoring and exponential retry backoff.
- Added tool-level reconnect handling for retriable connection errors (ECONNREFUSED, ECONNRESET, 404/502/503).
- Added `/mcp reconnect <name>` command for manual MCP server recovery.
- Improved reconnect robustness by aborting retries when MCP configuration changes via epoch checking.
- Extended transport reconnect handling to all transport types (stdio, HTTP/SSE) with unified onClose logic.
- Added comprehensive test coverage for MCPManager reconnect behavior and tool-level abort propagation.
- Replaced custom withAbort() implementation with untilAborted() utility from pi-utils for consistent abort handling.
- Extracted normalizeToolArgs() helper to consolidate argument normalization logic across renderCall(), renderResult(), and execute() methods.
- Added MCPToolCallParams type import to improve type safety for tool parameter handling.
- Fixed STT Alt+H mic cursor rendering to measure the actual microphone glyph width, preventing one-column TUI overflow crashes when the active symbol preset uses a wide icon (#484).
- Extracted mic cursor styling into dedicated method to consolidate color and width calculation logic.
Fixes#484
- Refactored MCP manager reconnection logic to track configuration changes via reconnectEpoch parameter.
- Consolidated error pattern matching in tool-bridge to use lowercase normalization for consistent comparison.
- Extracted retry provider variables to eliminate repeated ternary expressions in error handling.
- Reformatted code across multiple files for improved readability with consistent multi-line formatting.
- Added test coverage for transport reconnection scenarios including connection reuse after reconnection.
- Updated explore agent thinking level from off to med for improved reasoning.
- Simplified explore agent output schema: consolidated file references into single `ref` field with optional line ranges instead of separate `path`, `line_start`, `line_end` fields.
- Removed `code` section from explore agent output (critical code excerpts no longer extracted).
- Removed `dependencies`, `risks`, and `start_here` sections from explore agent output.
The 8e3e0ebf9 refactor centralized thinking inference but dropped
Bedrock-specific handling:
- inferAnthropicSupportedEfforts gated xhigh on anthropic-messages API,
excluding Bedrock models
- inferThinkingControlMode returned 'budget' for all Bedrock models
instead of 'anthropic-adaptive' for 4.6+
- parseAnthropicModel regex captured Bedrock date suffixes (20250819)
as version components, causing parseSemVer to return null
Fixes:
- Remove API guard from inferAnthropicSupportedEfforts so Opus 4.6+
gets xhigh regardless of API transport
- Add Anthropic version checks to Bedrock case in
inferThinkingControlMode (4.6+ adaptive, 4.5+ budget-effort)
- Narrow version regex from \d+ to \d{1,2} so date suffixes in
Bedrock model IDs are not absorbed
- Update four stale Bedrock Opus 4.6 entries in models.json
- Add thinkingBudgets.xhigh (default 32768) to settings schema
* feat: auto-reconnect MCP servers on connection loss
When an HTTP SSE stream drops (server restart, network interruption),
the transport fires onClose, and the manager proactively reconnects
with retry backoff (500ms, 1s, 2s, 4s). Tools are kept in the registry
during reconnection so they remain selected and available to the agent.
If proactive reconnection fails, stale tools stay registered. When the
agent calls one, the tool bridge detects the retriable connection error
(ECONNREFUSED, ECONNRESET, stale session 404/502/503, etc.), triggers
reconnectServer on the manager, and retries the call once on the fresh
connection. Concurrent reconnect attempts for the same server are deduped.
connectToServer now always installs a default onRequest handler for ping
and roots/list (using getProjectDir()), so all connections -- including
short-lived test/probe ones -- properly respond to server-initiated
requests during initialization.
Post-connection setup (resources, prompts, subscriptions) is extracted
into a shared #loadServerResourcesAndPrompts method used by both initial
connection and reconnection paths.
Add /mcp reconnect <name> command for manual recovery after extended
outages where both proactive and reactive reconnection have failed.
* docs: add changelog entry for MCP auto-reconnect
* fix: address P1 review findings in MCP reconnection
- Save server configs before connection attempt so deferred tools can
reconnect even when the initial connection timed out (P1-1)
- Make waitForConnection() and getConnectionStatus() aware of in-flight
reconnections so callers wait instead of failing immediately (P1-2)
- Add epoch counter incremented on disconnectAll() and checked in
connectAndWireServer() to invalidate stale reconnect attempts that
outlive a manager reset/reload (P1-3)
- Skip servers with pending reconnections in connectServers() to prevent
parallel connection attempts for the same server
* fix: deferred tool reconnect and non-blocking transport teardown
- DeferredMCPTool.execute now reconnects when getConnection() fails
("MCP server not connected"), not only on network errors from
callTool. Servers that missed the startup window can now be woken
by the first tool call against their cached tools. (P1-4)
- #doReconnect fire-and-forgets the old transport close instead of
awaiting it. HttpTransport.close() sends a DELETE with 30s timeout;
blocking here delayed the first reconnect attempt by that amount
on every server restart. (P1-5)
* fix: abort-aware reconnect waits and preserve tool selection on reconnect
- Wrap all reconnect() awaits with withAbort(signal) so user
cancellation (Esc) interrupts the reconnect backoff loop instead
of blocking for up to 7.5s. Applies to MCPTool (1 site) and
DeferredMCPTool (2 sites). (P2-1)
- Remove activateDiscoveredMCPTools call from /mcp reconnect handler.
refreshMCPTools already preserves the user's prior MCP tool
selection; the extra activation was silently opting into all
server tools including ones the user had not enabled. (P2-2)
* fix: rebind MCPTool connection after reconnect, add stdio retriable error
- MCPTool.connection is now mutable; after a successful reconnect retry,
this.connection is rebound to the fresh connection so subsequent calls
on the same instance (e.g. batched tool calls) use it instead of
triggering another reconnect cycle. (P2-3)
- Add "Transport closed" to RETRIABLE_PATTERNS. StdioTransport rejects
pending requests with this message when the subprocess dies, which
should trigger the reconnect path just like HTTP transport errors. (P2-4)
---------
Co-authored-by: Miroslav Drbal <miroslav.drbal@gendigital.com>
Co-authored-by: Can Bölük <can1357@users.noreply.github.com>
Apply user modelOverrides after hardcoded defaults so contextWindow
and other fields from models.json take precedence.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Simplified plan mode enforcement by removing tool retrieval and restoration logic.
- Replaced tool existence checks with registry lookup to reduce intermediate variables.
- Added automatic stripping of hashline display prefixes (LINE#ID:) from write tool content when hashline edit mode is enabled, preventing models from accidentally copying display markers into files.
- Implemented stripHashlinePrefixes() utility to remove hashline-only prefixes without affecting diff markers.
- Added stripWriteContent() helper to conditionally clean write content based on file display mode configuration.
- Updated write tool result message to notify users when hashline prefixes were auto-stripped.
- Added mcpServerName and mcpToolName optional properties to tool definitions for MCP server discovery and tool name tracking.
- Changed aborted tool call handling to preserve existing tool results instead of replacing with synthetic 'aborted' results at turn boundaries.
- Extracted flushPendingToolCalls() and flushPendingAbortedToolCalls() helpers to consolidate orphaned tool call handling logic.
- Updated tool result handling to use message timestamps instead of Date.now() for synthetic results consistency.
* feat(mcp): implement roots/list and server-to-client request handling
Add support for MCP server-to-client JSON-RPC requests across both
stdio and HTTP transports, enabling servers to query client capabilities
such as roots/list during initialization.
Transport layer (types.ts, stdio.ts, http.ts):
- Add onRequest callback to MCPTransport interface for server-initiated
requests; add toJsonRpcError helper for error code propagation
- Classify incoming messages by checking method+id (request), id-only
(response), method-only (notification); guard against id:null per
JSON-RPC 2.0 spec
- StdioTransport: detect server requests in #handleMessage, respond via
#sendResponse writing JSON-RPC response to subprocess stdin
- HttpTransport: detect server requests via #dispatchSSEMessage across
all SSE streams (dedicated listener, POST response drain, notify
piggybacking), respond via #sendServerResponse POST with proper
Accept header and session ID
- Refactor startSSEListener to resolve once SSE GET connects (not when
stream ends), enabling await before notifications/initialized; reset
#sseConnection via .finally() for reconnection after transient failure
- #parseSSEResponse continues reading after capturing the primary
response to drain piggybacked server requests/notifications; clears
timeout after capture so drain phase is unbounded
- notify() reads text/event-stream response bodies for piggybacked
messages; cancels non-SSE response bodies to release connections
- #sendServerResponse includes AbortSignal.timeout and cancels response
body; fire-and-forget handlers wrapped in try/catch to prevent
unhandled rejections
Client wiring (client.ts):
- Add onRequest to connectToServer options, wire to transport before
initialization
- Add awaitable onInitialized hook in initializeConnection, called
between initialize response (which sets session ID) and initialized
notification, so SSE stream is open when server sends roots/list
- Pass only signal to transport.request (not full options object)
- Hoist transport ref to outer scope; close on timeout/abort to prevent
orphaned transports when SSE GET hangs
Manager (manager.ts):
- Wire onRequest handler in connectServers for all MCP connections
- Handle roots/list by returning project CWD as file:// URI via
pathToFileURL; return -32601 for unsupported methods
Tests (mcp-roots-list.test.ts):
- toJsonRpcError: code extraction, defaults, non-Error values
- Message classification spec tests: request/response/notification/
unknown dispatch, id:null and id:0 edge cases
- Roots response shape: file:// URI generation, Windows paths, spaces
* fix(mcp): return SSE response immediately instead of blocking on stream drain
The #parseSSEResponse loop continued iterating the SSE stream after
capturing the response for the expected request ID. Since clearTimeout
was called after capture, a server that holds the SSE stream open for
follow-up events (permitted by Streamable HTTP) would block the
request() call indefinitely.
Return the result as soon as it's captured and drain remaining
messages in a detached background task via #readSSEStream, which
already handles dispatch and error swallowing.
* fix(mcp): handle batched JSON-RPC messages in both transports
JSON-RPC 2.0 section 6 allows sending an array of request/notification
objects as a batch. If a server sent a batch, the message classifier
in both transports would fail the 'method in message' check on the
array object and silently drop all contained messages.
Add an Array.isArray guard at the top of #handleMessage (stdio) and
#dispatchSSEMessage (http) that recurses into each element. Defensive
measure — no known MCP server sends batches today, but the guard is
cheap and correct per the JSON-RPC spec.
* fix(mcp): address second Codex review round
- http: break from SSE loop before starting background drain to avoid
ReadableStream locked error (the for-await iterator still holds the
reader when #drainSSEBackground was called inline)
- types: toJsonRpcError now accepts plain { code, message } objects,
not just Error instances, so onRequest handlers can throw structured
JSON-RPC errors without wrapping in Error
- test: relax Windows path name assertion to toBeTruthy since
path.basename is platform-dependent for backslash paths; add tests
for plain-object toJsonRpcError
* fix(mcp): address third Codex review round
- parseSSEResponse: flatten JSON-RPC batch arrays before checking for
the expected response, so a server that batches the primary response
with piggybacked requests/notifications in a single SSE event still
has the response extracted correctly
- sendServerResponse: retry once on 401/403 via onAuthError, matching
the auth-refresh logic in #executeRequest; prevents server-initiated
request replies from failing after token expiry on long-lived SSE
sessions
---------
Co-authored-by: Miroslav Drbal <miroslav.drbal@gendigital.com>
- Added automatic deduplication of identical context files by content, keeping the closest (lowest depth) copy when duplicates are discovered.
- Implemented dedupeExactContextFiles() function to filter duplicate context entries in both explicit and discovered file lists.
- Added 3 test cases covering deduplication of explicit context entries, discovered context entries, and preservation of distinct entries.
- Added `edit.blockAutoGenerated` setting to control enforcement of auto-generated file detection.
- Improved auto-generated file detection to use language-specific comment parsing instead of broad regex patterns, reducing false positives.
- Enhanced marker detection to scan only leading header comments (1024-byte limit) rather than entire file prefix for better accuracy.
- Fixed tool argument validation to properly handle string 'null' values on optional LLM tool arguments.
- Improved type safety by changing validateToolCall and validateToolArguments return types from any to ToolCall["arguments"].
- Added auto-generated file detection guard to prevent modification of generated code in Edit and Write tools.
- Implemented checkAutoGeneratedFile() to validate file paths against auto-generated markers (protoc, sqlc, buf, swagger).
- Implemented checkAutoGeneratedFileContent() to scan file content prefix for auto-generated patterns before processing.
- Added pre-write validation in Write tool to block overwriting of auto-generated files.
- Added `args` field to ShellResult to capture the executed command.
- Added `exit_code` property to ShellResult as an alias for `returncode`.
- Added `check_returncode()` method to ShellResult to raise CalledProcessError on non-zero exit codes.
- Renamed `code` field to `returncode` in ShellResult with backward-compatible `code` property.
- Updated `run()` command documentation to clarify available ShellResult fields.
- Extracted OpenAI compatibility detection and resolution logic into dedicated `openai-completions-compat` module.
- Refactored `detectCompat()` and `getCompat()` to delegate to new compat module functions with simplified conditional logic.
- Fixed OAuth redirect URI validation to preserve exact configured values without trailing slash normalization.
- Improved session deletion to return boolean status and display error messages in UI instead of silently failing.
- Added `/session delete` command with Delete key support and confirmation dialogs for session management.
- Made sessionDir parameter optional in SessionManager.create(), forkFrom(), continueRecent(), and list() methods with automatic default computation.
- Updated SessionManager.getDefaultSessionDir() to accept optional agentDir parameter for custom sessions root configuration.
- Changed SessionManager.list() signature to require cwd parameter as first argument with sessionDir now optional.
- Implemented multi-root session migration support by replacing global migration state with per-root tracking and extracting session directory encoding logic.
- Added resolveManagedSessionRoot() function to determine if session directory is managed and extract its root.
- Added symlink and path alias resolution to session directory handling for consistent behavior across aliased home and temp directories.
- Improved status line path display to strip display roots using canonical path resolution, correctly handling symlink-equivalent directory aliases.
- Added support for quoted paths in grep, ast_grep, and find tools to properly handle directory names with spaces.
- Improved ast_grep error messaging when no matches found with parse errors to suggest narrowing path/glob or setting language.
- Extracted path utility functions (resolveEquivalentPath, normalizePathForComparison, pathIsWithin, relativePathWithinRoot) to shared utils package.
- Added comprehensive test coverage for symlink alias resolution in status line path rendering and session directory handling.
- Added support for quoted paths in grep, ast_grep, find, and ast_edit tools to handle paths with spaces.
- Introduced normalizePathLikeInput() utility function for consistent path and glob parameter normalization across tools.
- Enhanced ast_grep error messaging to warn about parse issues and suggest narrowing path/glob or setting lang parameter.
- Added comprehensive tests for quoted path handling in grep, ast_grep, and find tools with pattern matching.
- Added overload for `prompt()` method accepting string input with optional options parameter.
- Added type guard `supportsMCPToolDiscoveryExecution()` with `MCPDiscoveryExecutionSession` type predicate for safer session type narrowing.
- Added default parameter value to `refreshToolChoiceForActiveTools()` for improved robustness.
* Add MCP tool discovery search and live refresh
* Fix MCP discovery review feedback
* Address remaining MCP discovery review comments
* feat: compact MCP discovery search results
* fix: align MCP discovery search contract
* feat: add MCP server tool counts to discovery hints
* fix(agent): corrected stale toolChoice validation against active tools
- Fixed stale forced toolChoice passed to provider after mid-turn tool refresh by validating against active tools.
- Added refreshToolChoiceForActiveTools() to filter invalid tool choices when available tools change.
- Changed getToolChoice config to use computed function instead of static property for dynamic validation.
- Fixed MCP tool selection tracking in coding-agent to distinguish between discovery-enabled and non-discovery sessions.
- Updated search_tool_bm25 to filter already-selected tools before applying limit parameter.
---------
Co-authored-by: can1357 <me@can.ac>
- Updated llama.cpp model discovery to read context window from the `/props` endpoint's `default_generation_settings.n_ctx` field instead of using hardcoded 128000 default.
- Updated llama.cpp model discovery to detect vision capabilities from the `/props` endpoint's `modalities.vision` field instead of defaulting to text-only input.
- Changed llama.cpp `maxTokens` calculation to respect discovered context window limits, capping at 8192 or the server's context window, whichever is smaller.
- Added `#toLlamaCppNativeBaseUrl()` helper to normalize llama.cpp base URLs by stripping `/v1` suffix for native endpoint access.
- Added 3 test cases to verify context window, vision capability, and authorization header handling in llama.cpp discovery.
- Added automatic Ollama model context window discovery from metadata for accurate token limits.
- Added `attribution` option to `PromptOptions` for explicit billing and initiator attribution control.
- Added automatic clearing of completed and abandoned todo tasks after ~1 minute.
- Changed session directory migration to use `-tmp-` prefix instead of double-dash format.
- Updated Ollama model registration to use discovered context window instead of hardcoded 128000 token default.
Fixes#440