- Removed ancestor directory walking logic from codex and opencode skill loading. Simplified project skills discovery to use single project directory instead of scanning up the filesystem tree. Fixed variable shadowing issues in gemini and github context file loading.
NanoGPT exposes per-thinking-level model IDs (e.g.
anthropic/claude-opus-4.6:thinking:low) as separate entries. These
pollute the model list and collide with parseModelString's thinking
level suffix stripping.
Filter out all :thinking and :thinking:level suffixed nanogpt models
during discovery. When a :thinking variant existed, mark the
corresponding base model as reasoning-capable. NanoGPT already supports
reasoning_effort via the OpenAI-compat path so no provider-side model
ID suffixing is needed.
- Added buildCompactHashlineDiffPreview() function to generate collapsed diff previews for tool responses.
- Enhanced EditTool response to include diff summary with added/removed line counts and compact preview.
- Added project-level discovery for .agent/ and .agents/ directories walking up to repository root.
- Implemented helper functions for truncating long diff runs (collapseFromStart, collapseFromEnd, collapseFromMiddle).
- Clarified pos semantics for replace, prepend, and append operations with concise bullet format.
- Simplified lines parameter documentation to focus on practical usage patterns.
- Rewrote rules section to emphasize structural anchoring and when to use prepend/append versus range replace.
* feat: monorepo-friendly discovery for AGENTS.md and skills
Support hierarchical config discovery in monorepos by walking up from
cwd through ancestor directories, combining files from all levels
instead of only checking the immediate working directory.
AGENTS.md context files:
- Change dedup key from file.level to file.level + depth, so context
files at different directory levels coexist instead of shadowing
- Root AGENTS.md and sub-project AGENTS.md are both included in the
system prompt, ordered from least specific to most specific
Skills:
- Modify all 4 providers with project-level skill directories (native,
claude, codex, opencode) to walk up from cwd through ancestors,
scanning for skills at each level
- Skills at closer directories win on name conflicts via existing
name-based dedup
Repo root boundary:
- Add findRepoRoot() utility that detects .git to identify repo root
- Add repoRoot field to LoadContext, computed once in loadCapability()
- All walk-up traversals (AGENTS.md, skills, nearest config dir) stop
at the repo root, preventing discovery from leaking outside the repo
- When not in a git repo, falls back to walking to filesystem root
Files changed:
- capability/fs.ts: add findRepoRoot()
- capability/types.ts: add repoRoot to LoadContext
- capability/index.ts: compute repoRoot in loadCapability()
- capability/context-file.ts: depth-aware dedup key
- discovery/agents-md.ts: bound walk-up at repo root
- discovery/builtin.ts: getAncestorDirs stopAt param, skill walk-up
- discovery/claude.ts: skill walk-up with repo root bound
- discovery/codex.ts: skill walk-up with repo root bound
- discovery/opencode.ts: skill walk-up with repo root bound
- extensibility/skills.ts: add repoRoot to inline LoadContext
* feat(agents-provider): add project-level discovery with ancestor walk-up for all capability types
The agents provider (.agent/.agents directories) previously only loaded
capabilities from the user home directory (~/.agent/, ~/.agents/). This
meant project-level .agents/ directories in monorepo roots were not
discovered when sessions started from subdirectories.
Add getProjectPathCandidates() helper that walks from cwd up to repoRoot,
scanning both .agent/ and .agents/ at each ancestor level. Apply this to
all six capability types: skills, rules, prompts, commands, context files
(AGENTS.md), and system prompts (SYSTEM.md). This matches the ancestor
walk-up behavior already present in the builtin (.omp), claude, codex,
and opencode providers.
All loaders now parallelize project-level and user-level scans via
Promise.all. Project-level results appear closest-first so dedup at the
capability layer picks the nearest override.
* fix(discovery): remove hard cap of 20 on ancestor directory walking
All walk-up loops already terminate naturally at repoRoot or filesystem
root. The depth < 20 / .slice(0, 20) / MAX_DEPTH caps were redundant
safety guards that would silently stop discovery in deeply nested
projects.
Removed from: agents.ts, agents-md.ts, builtin.ts, claude.ts, codex.ts,
opencode.ts, and corresponding test files.
* fix(agents-provider): set depth on project-level ContextFile entries for correct dedup
loadContextFiles was creating project-level ContextFile entries without
a depth field. Since contextFileCapability.key uses
`project:${file.depth ?? 0}`, all ancestor-level AGENTS.md files
collapsed to the same key and only the first survived dedup.
Compute depth via calculateDepth(cwd, ancestorDir) where ancestorDir is
two levels up from the file path (past the .agent/.agents config dir).
This gives each ancestor level a distinct dedup key.
* fix(discovery): stop ancestor walk-up at $HOME when not in a git repo
When repoRoot is null (no .git found), walk-up loops traversed all the
way to filesystem root. This caused $HOME to be scanned as a project-
level directory and then again as user-level, producing duplicates.
All providers now use `ctx.repoRoot ?? ctx.home` as the stop boundary:
stop at repoRoot if in a repo, otherwise stop at home. Applied to
agents.ts, agents-md.ts, builtin.ts, claude.ts, codex.ts, and
opencode.ts.
* fix(context-files): clamp depth >= 0 in dedup key and fix provider depth computations
The dedup key `project:${file.depth}` used raw depth, which could be
negative when providers computed it from config subdirectories (e.g.
.claude/, .github/, .gemini/) rather than the ancestor directory. This
caused same-scope cwd-level files to get distinct keys like project:-1
and project:0, bypassing dedup and injecting conflicting instructions.
Two-layer fix:
1. Key function: clamp to Math.max(0, depth) so any file at or below
cwd is treated as cwd-scope (depth 0). Defensive against future
providers.
2. Providers: fix root cause in claude.ts, gemini.ts, github.ts to
compute depth from the ancestor directory (parent of the config
subdir), not the config subdir itself.
---------
Co-authored-by: Can Bölük <can1357@users.noreply.github.com>
parseModelString now extracts valid thinking level suffixes (e.g.,
"anthropic/claude-opus-4-6:high") instead of treating them as part of
the model ID. This enables per-role thinking levels in config:
modelRoles:
slow: anthropic/claude-opus-4-6:high
default: anthropic/claude-opus-4-6:low
smol: google/gemini-3-flash:medium
The thinking level is applied at startup, in SDK fallback resolution,
and during Ctrl+P role cycling. The original config string is preserved
on role cycle so the suffix round-trips correctly.
* idiomatic rust fixes
* idiomatic rust fixes
* display an image if we are fetching an image
* MIME type strictness
* codex nagging me
* resize so we do not blow up the terminal we are in
* codex nagging
* codex nagging
* codex nagging
* codex nagging
* codex nagging
---------
Co-authored-by: Brit <lol@no.com>
- Added language module with 39 supported languages and tree-sitter parser bindings for ast-grep integration.
- Exported dedupeParseErrors utility function to remove duplicate parse error messages in tool output.
- Fixed duplicate parse error messages when multiple patterns fail on the same file.
- Replaced language alias lookup with O(1) phf::Map and added 30+ new language aliases (golang, julia, toml, zig, etc.).
- Migrated from ast-grep-language to direct tree-sitter language dependencies for improved language support.
- Added `fetch.useKagiSummarizer` configuration setting to toggle Kagi Universal Summarizer usage in fetch tool.
- Updated fetch tool to conditionally apply Kagi summarization based on configuration setting.
- Added comprehensive test coverage for Kagi summarizer toggle behavior with mocked dependencies.
- Added Bun version validation at startup to enforce minimum version 1.3.7 for JSONL session parsing.
- Fixed `/resume` and `--resume` flags silently failing on older Bun runtimes by adding version check.
Fixes#277
- Refactored hlineref Handlebars helper to return JSON-quoted strings for safer JSON embedding in prompts.
- Improved hashlineParseText to preserve blank lines and trailing empty strings while normalizing line endings.
- Optimized duplicate line detection in range replacements using trimmed comparison to reduce whitespace false positives.
- Removed await from stream() calls that return async iterables directly.
- Removed await from synchronous utility functions like findApiKey(), resolvePythonRuntime(), and getToolPath().
- Removed await from prerenderMermaid() and findExaKey() calls that don't require awaiting.
- Converted clipboard copy operation from async to synchronous execution across native and TypeScript layers.
- Simplified copy_to_clipboard return type from task::Async<()> to Result<()> in Rust implementation.
- Removed promise chains and async/await from clipboard handlers in command and input controllers.
- Updated clipboard module documentation to explain synchronous execution avoids AppKit pasteboard warnings.
- Reordered fix:rs script to run cargo fmt before cargo clippy for consistent formatting.
- Added Kagi Universal Summarizer integration for URL and YouTube video summarization with fallback support.
- Exported `searchWithKagi` and `summarizeUrlWithKagi` functions from new shared `web/kagi` module for reuse across components.
- Changed HTML-to-text rendering priority to attempt Kagi summarization first before Jina, Trafilatura, and Lynx.
- Refactored Kagi search provider to use shared utilities from `web/kagi` module, reducing code duplication.
- Added `KagiApiError` exception class for Kagi API-specific error handling with optional status code tracking.
- Fixed fetch result rendering to properly wrap long lines instead of truncating them.
- Replaced Bun.wrapAnsi with unified wrapTextWithAnsi utility across debug and output modules.
- Corrected content preview calculation to use actual wrapped line count instead of truncated count.
- Applied tab escaping to tool output rendering to prevent display misalignment.
- Imported replaceTabs utility and applied it consistently across 4 output rendering paths.
- Added `/login <provider>` command for direct OAuth provider login with automatic selector routing.
- Added Kagi API key authentication support as new OAuth provider across ai and coding-agent packages.
- Added optional `providerId` parameter to `showOAuthSelector()` for direct provider selection without manual input.
- Simplified web search result formatting by removing empty sections (Answer, Sources, Meta, Related).
- Fixed MCP tool schema dereferencing and Ajv validation warnings for non-standard format keywords.
- Refactored OAuth login/logout logic into extracted handler methods for improved maintainability.
- Add dereferenceJsonSchema() that inlines local $ref pointers and strips
$defs/definitions from MCP tool schemas before they reach LLM providers.
Previously, Anthropic's convertTools() extracted only properties/required,
dropping $defs and leaving dangling $ref — the LLM never saw the actual
type definitions (e.g. SourceAnchorInput enum values from nucleus).
- Silence Ajv logger (logger: false) on all three instances that use
strict: false. MCP servers may declare non-standard format keywords
(e.g. "uint") that caused console.warn() to corrupt TUI output.
- Cache compiled Ajv validators per schema object identity in validation.ts,
eliminating redundant recompilation on every tool call.
Co-authored-by: Miroslav Drbal <miroslav.drbal@gendigital.com>
- Condensed five detailed rules into four concise ones with clearer guidance on inclusive `end`, indentation, and verification.
- Simplified JSON examples to single-line format for brevity.
- Merged and refocused examples to highlight common pitfalls: boundary inclusion, block scope, sibling spacing, and anchor disambiguation.
- Fixed resource refresh tracking by storing connection references alongside promises to prevent stale deduplication.
- Fixed update target resolution to explicitly handle missing ompPath and use path.resolve() for consistent normalization.
- Added error handling and logging in Smithery registry detail fetching to gracefully handle failures and track issues.
- Fixed virtualization context cleanup in error paths to prevent partially-started instances from remaining active.
- Fixed API key retrieval to use dynamic provider configuration instead of hardcoded provider string.
- Enhanced test utilities to capture and verify request parameters for improved test coverage and debugging.
- Added mcp:// internal URL protocol for reading MCP server resources via the read tool.
- Removed read_resource tool; MCP resource reading now integrated into read tool with mcp:// URLs.
- Implemented McpProtocolHandler with URI template matching for resolving MCP server resources.
- Updated MCP resource notifications to recommend read(path="mcp://<uri>") syntax.
* Implemented Smithery MCP Searchable Registry
* refactor(coding-agent): consolidated MCP registry search and improve error handling
- Extracted `parseCommandArgs` and `stripControlChars` utilities to reduce duplication in MCP command controller. Replaced custom URL opening logic with centralized `openPath` utility across OAuth and registry flows.
- Enhanced Smithery auth error handling to gracefully degrade on file read failures with logging instead of throwing, and improved chmod error reporting. Normalized Smithery API base URL to strip trailing slashes.
- Improved registry search pagination to fetch multiple pages until sufficient results are found, with semantic mode support to preserve API relevance ranking. Deduplicated entries by identity key and applied local sorting only in non-semantic mode.
---------
Co-authored-by: can1357 <me@can.ac>
- Add a dedicated abortReason field to SingleResult and thread it through task execution paths so aborted subagents show actionable context instead of a generic badge.
- Populate abortReason for signal cancellation, pre-start cancellation, submit_result aborted status, and missing submit_result after reminders
Fixes#248
- Fixed URI template matching to handle empty string expansions in MCP resource queries.
- Fixed LM Studio URL validation to preserve invalid baseUrl instead of applying localhost fallback.
- Fixed MCP notification epoch handling to prevent unsubscribe calls when old subscriptions resolve after re-enabling.
- Extracted hardcoded LM Studio base URL to named constant for improved maintainability.
- Refactored notification epoch check logic for improved code clarity and readability.
- Normalize LM Studio discovery URLs to avoid duplicated /v1 segments
- Harden status-line PR cache with branch+repo context validation and guarded async writes
- Apply Foundry auth precedence correctly and preserve system trust roots when custom CA is provided
- Split Copilot premium multiplier handling by plan tier while preserving agent-initiated zero billing
- Catch MCP notification refresh failures and route read_resource via deterministic full template matching
- Add regression tests for each fix cluster and keep targeted suites green
- Clarified range selection guidance for hashline tool to prevent orphaned braces and duplication errors.
- Updated example to demonstrate correct end-range boundary inclusion in replace operations.
* feat: Add LM Studio as a supported model provider with OpenAI-compatible API fetching and discovery.
Add LM Studio as a supported AI provider with optional API key, environment variables, and discovery.
* feat: Add rustup as a dev dependency.
* fix: Refine LM Studio API key handling to conditionally send authorization headers during model discovery based on whether the key is a default local token or a custom key, and add new tests.
* feat: Enhance OAuth token and account ID resolution for model providers in the model registry.
* rebase for packages/ai/CHANGELOG.md
* feat: improve implicit model discovery to independently auto-detect Ollama and LM Studio, and refine LM Studio base URL handling.
---------
Co-authored-by: Can Bölük <can1357@users.noreply.github.com>
* feat(mcp): resource notifications, subscriptions, and read_resource builtin tool
- Add MCP resource subscription lifecycle (subscribe/unsubscribe on connect/disconnect)
- Wire mcp.notifications setting with live toggle support
- Add debounced followUp injection for resource change notifications
- Add global read_resource builtin tool with server resolution by URI/template scheme
- Add MCP prompt commands (buildMCPPromptCommands) with array content support
- Add server instructions injection into system prompt with attribution
- Add mcp.notificationDebounceMs configurable setting
Client (client.ts):
listResources, listResourceTemplates, readResource with pagination
subscribeToResources, unsubscribeFromResources
listPrompts, getPrompt, serverSupportsPrompts
serverSupportsResources, serverSupportsResourceSubscriptions
Manager (manager.ts):
Notification dispatch with subscribed-URI guard
Concurrent refresh deduplication via pending promise map
setNotificationsEnabled with subscribe/unsubscribe toggle
Tests:
client-resources.test.ts (31 tests)
client-prompts.test.ts (20 tests)
mcp-read-resource.test.ts (13 tests)
* fix(mcp): address PR review - eager prompt init and stale subscription cleanup
P1: Make setOnPromptsChanged eagerly fire for servers that already
have prompts loaded. The callback is registered after MCP discovery
has already loaded prompts and fired the hook, so without this the
handler is never called on the common startup path. The fix is in
the manager itself (not the caller), eliminating the race condition
regardless of when the callback is wired.
P2: Unsubscribe removed resource URIs on resource refresh.
refreshServerResources was subscribing to the new URI set and
overwriting #subscribedResources without unsubscribing URIs that
were previously subscribed but no longer present, leaving stale
subscriptions active on the server.
* fix(mcp): add resources and prompts to /mcp help text and subcommand completions
* feat(mcp): add /mcp notifications command
Shows per-server notification capabilities with subscription state:
- Lists supported notification types (tools/list_changed, resources/list_changed,
prompts/list_changed) with check marks
- Shows resources/subscribe status with active subscription count
- Lists subscribed URIs with green ticks when notifications are enabled
- Displays overall enabled/disabled state (mcp.notifications setting)
* fix(mcp): address PR review comments on race conditions and stale state
- Await subscribe/unsubscribe in refreshServerResources so the refresh
promise doesn't resolve before subscriptions are settled, preventing
a second refresh from racing and overwriting tracking state (P2 #3)
- Guard setNotificationsEnabled subscribe .then() against a disable
that happens while the subscribe request is in-flight (P2 #5)
- Re-check mcp.notifications setting inside debounce setTimeout
callback so toggling off mid-window actually suppresses the
follow-up message (P2 #4)
- Fire onToolsChanged and onPromptsChanged callbacks in
disconnectServer so stale slash commands and tool registrations
are cleaned up when a server is removed (P2 #2)
---------
Co-authored-by: Miroslav Drbal <miroslav.drbal@gendigital.com>
* Add PR number segment to status bar
Add a new 'pr' status line segment that shows the GitHub PR number
(e.g., #1234) as a clickable OSC 8 hyperlink when the current branch
has an associated pull request.
- Async lookup via 'gh pr view', cached per branch
- Invalidates on branch change via .git/HEAD watcher
- Falls back to hidden segment when no PR exists or gh unavailable
- Supports all theme presets (unicode, nerd font, ascii)
- Added to all preset layouts after the git segment
* Skip PR lookup on default branch, resolve dynamically
* Extract git-utils, add tests for parseGitHubRepo and parseDefaultBranch
* Fix PR lookup race condition, invalidation churn, and dotted repo names
- Guard #cachedPr writes against branch change during in-flight lookup
- Stop clearing PR cache in invalidate() (only .git/HEAD watcher should)
- Allow dots in GitHub repo names in parseGitHubRepo regex
* Simplify PR lookup: use gh pr view, try upstream/HEAD for default branch
- Replace gh pr list --head with gh pr view (requires gh repo set-default)
- Remove manual remote URL resolution — gh handles it
- Default branch detection falls back to upstream/HEAD when origin/HEAD is unset