- Added checks to filter out Kitty release events (event_type 3) in both matches_key_inner and parse_key_inner functions. Added comprehensive tests for both key matching and input handling to verify release events are ignored while press and repeat events are still processed correctly.
Fixes#325
- Removed sysinfo, bstr, and heapless dependencies from pi-natives. Removed transitive dependencies from Cargo.lock including byteorder, hash32, ntapi, objc2-io-kit, and windows 0.62.2.
- 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.
- 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.
- 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.
- Enforced tool decision in plan mode--agent now requires calling either `ask` or `exit_plan_mode` when a turn ends without a required tool call.
- Fixed cancellation behavior of `ask` tool to abort the current turn instead of returning a normal cancelled selection, while timeout-driven auto-cancel still returns without aborting.
- Added plan-mode-tool-decision-reminder system prompt to guide agent when required tools are not called.
- Improved agent_end event handling to use fallback assistant message when #lastAssistantMessage is unavailable.
- Fixed strikethrough reset logic to properly handle combined underline and strike attributes without resetting colors.
- Refactored write_line_end_reset to emit correct ANSI codes (24m for underline, 29m for strike) when both attributes are present.
- Added test case verifying strikethrough resets at line wraps while preserving foreground and background colors.
- Added TypeScript test case for strikethrough styling behavior across wrapped lines.
Remove the non-empty validation on `out` in both the TypeScript tool
layer and the Rust native layer. An empty replacement template now
deletes the matched AST node, which is the natural semantics.
Also remove .trim() calls on pattern and rewrite strings — trimming
silently destroys intentional whitespace and serves no purpose since
ast-grep matches on AST structure, not raw text.
BREAKING CHANGE: ast_find parameter 'pattern' (string) is replaced by
'patterns' (string[]). ast_replace parameters 'pattern' + 'rewrite' are
replaced by 'ops: Array<{ pat: string; out: string }>'.
Native (pi-natives / crates/pi-natives):
- astFind accepts patterns[] array; all patterns run per file, results
merged and sorted by path/line/column before offset+limit are applied
- astReplace accepts rewrites Record<string,string>; all patterns compiled
once upfront and applied per file in a single pass
- Deterministic result ordering via BTreeSet/BTreeMap
Coding-agent tools:
- ast_find: multi-pattern deduplication, '>>' prefix on match-start lines,
padded line numbers, directory-tree grouping (# dir / ## └─ file headers),
scopePath/files/fileMatches in tool details
- ast_replace: ops[] interface with duplicate-pattern rejection, diff-style
(-before/+after) previews grouped by directory, parse errors shown on
zero-replacement path, fileReplacements in tool details
- Tool prompts updated to document new interfaces with multi-pattern examples
- Task item id maxLength raised from 32 to 48 characters
- Added ast_replace tool test suite
Rust (crates/pi-natives/src/ast.rs):
- Expand supported languages from 7 to all 25 ast-grep tree-sitter
languages: Bash, C, C++, C#, CSS, Elixir, Go, Haskell, HCL, HTML,
Java, JavaScript, JSON, Kotlin, Lua, Nix, PHP, Python, Ruby, Rust,
Scala, Solidity, Swift, TSX, TypeScript, YAML.
- Pre-filter file candidates by language-resolvable extension before
reading or parsing. Non-code files (.md, .zip, .bin, .gitignore, etc.)
are silently skipped instead of producing misleading parse errors.
- Make canonical_lang_name exhaustive over SupportLang so the compiler
flags new variants on upstream upgrades.
TypeScript (ast-find.ts, ast-replace.ts):
- Format match output with hashline tags (LINE#HASH:content) when
hashline mode is active, consistent with read/grep tool output.
Falls back to plain line numbers when hashline mode is off.
- ast_find now emits all lines of a multiline match instead of a
single truncated preview line.
Prompts:
- Add AST pattern syntax reference (metavariables, wildcards, variadics)
to the system prompt.
- Add examples and scoping guidance to ast-find.md and ast-replace.md.
- Added ast_find and ast_replace tools for syntax-aware structural code search and rewriting via ast-grep.
- Added astFind.enabled and astReplace.enabled configuration settings to control tool availability.
- Implemented native AST module with pattern matching, language inference, and edit application for 7 languages.
- Added system prompt guidance to prefer AST tools over bash text manipulation for syntax-aware operations.
- Consolidated @oh-my-pi/pi-utils subpath imports into single package root import across 100+ files.
- Moved tryParseJson utility from local web scrapers module to @oh-my-pi/pi-utils package for centralized JSON parsing.
- Renamed loadSkillsFromDir to scanSkillsFromDir and refactored skill discovery to use fs.promises.readdir instead of glob-based approach.
- Replaced custom parseJSON with tryParseJson across discovery modules for consistent error handling.
- Removed emitCustomToolSessionEvent method and cleanupSshResources function, consolidating shutdown logic into dispose method.
- Updated glob pattern construction to use GlobBuilder with literal_separator(true) for improved path handling.
- Added a `display.tabWidth` setting to control default tab rendering.
- Integrated `.editorconfig` resolution for c ontext-aware tab indentation.
- Updated native text processing to use the resolved tab width for calculations.
- Improved tab visualization in diffs and other UI elements for consistency.
- Added cancellation callback support to read builtin via generic parameter on read_line() method.
- Implemented platform-specific input waiting using poll() on Unix systems for cancellation checks.
- Refactored OpenFile to Stdio conversion from trait impl to fallible into_stdio() method with proper error handling.
- Added ensure_not_cancelled() method to detect and handle cancellation state in read operations.
- Added per-command `pty` parameter to bash tool for fine-grained PTY mode control.
- Removed global `bash.virtualTerminal` setting in favor of per-command PTY parameter.
- Fixed potential deadlock in shell session cleanup by replacing blocking lock with non-blocking try_lock.
- Updated async session key generation to include jobId for improved session isolation.
- Removed the `getSystemInfo` API and `SystemInfo` type from package exports by deleting the `system-info` Rust/TS modules, dropping the `system_info` crate module, and removing top-level `system-info` re-exports.
- Updated environment information generation to no longer rely on native system-info data, sourcing distro and kernel values from built-in `os` APIs instead and removing the `Disk` field from produced environment entries.
- Adjusted native binding validation to stop requiring `getSystemInfo`, reflecting the new binding contract after API removal.
- Added startup-debug instrumentation behind `PI_DEBUG_STARTUP` that traces native addon loading, extraction, AVX2 detection, and environment info/GPU caching steps for diagnostics.
- Added support for braced escape sequences (\p{...}, \P{...}, \x{...}, \u{...}) in regex pattern sanitization to properly preserve unicode property escapes and hex escapes.
- Improved LSP client message writing by simplifying header encoding and refactoring abort signal handling with the untilAborted utility.
- Enhanced native addon installation script to dynamically fetch release tags from GitHub API instead of using hardcoded versions.
- Relaxed native addon validation to only error when no addons are found rather than when any are missing, improving flexibility in addon availability.
- Added Brave web search provider with support for query, result count, and recency filtering.
- Added BRAVE_API_KEY environment variable configuration for Brave search authentication.
- Updated web search provider priority order to include Brave as second-highest priority after Exa.
- Extended recency filter support to Brave search provider alongside Perplexity.
- Implemented BraveProvider class with API integration, response mapping, and parameter validation.
- Added helper functions for recency mapping, result clamping, and snippet building in Brave provider.
Patterns like `\${platform}` or `a{b}` contain braces the regex engine
rejects as malformed repetitions. The new sanitize_braces() preprocessor
escapes { and } that do not form valid quantifiers ({N}, {N,}, {N,M})
before compiling, making grep resilient to literal template strings.
- Removed unnecessary blank lines in glob.rs, glob_util.rs, and grep.rs.
- Reformatted multi-line doc comment in glob_util.rs for consistency.
- Collapsed assert_eq! calls in glob_util.rs tests to single lines.
- Extracted shared glob pattern utilities into a new `glob_util` module to reduce code duplication between `glob` and `grep` modules.
- Moved `build_glob_pattern()` and `compile_glob()` functions from `glob.rs` and `grep.rs` into the centralized `glob_util` module.
- Added `try_compile_glob()` helper function to handle optional glob pattern inputs with proper error handling.
- Implemented `fix_unclosed_braces()` utility to automatically close unmatched opening braces in glob patterns, improving robustness with LLM-generated patterns.
- Added `recursive` option to GlobOptions to control whether simple glob patterns match recursively by default (true).
- Changed glob pattern behavior to always apply recursive matching for simple patterns instead of requiring explicit `**/` prefix.
- Improved symlink handling in glob file type filters to resolve symlink targets and match based on their actual type (file/dir).
- Enhanced skill discovery in coding-agent to use dual-pass glob approach with deduplication and improved extension module detection.
- Implemented dynamic Tailwind CSS compilation in stats package by extracting actual class names from source files instead of building with empty candidates.
- Refactored Tailwind stylesheet imports to use centralized `tailwindcss/index.css` import with custom stylesheet loader callback.
- Added `sanitizeText` function to pi-natives that strips ANSI escape sequences, removes control characters and lone surrogates, and normalizes line endings.
- Moved `sanitizeText` function from `@oh-my-pi/pi-utils` to `@oh-my-pi/pi-natives` for better code organization and native performance.
- Added line length clamping (4000 characters) to bash and Python execution output to prevent excessively long lines.
- Replaced internal `#normalizeOutput` methods with `sanitizeText` utility function in bash and Python execution components.
- Fixed bash interactive tool to gracefully handle malformed output chunks by normalizing them with `sanitizeText`.
- Simplified documentation by removing WASM terminology from package descriptions and comments.
- Added optional `cache` parameter to `glob()`, `grep()`, and `fuzzyFind()` functions to enable shared filesystem scan caching.
- Added new `invalidateFsScanCache()` function to allow manual invalidation of filesystem scan cache entries.
- Improved filesystem path canonicalization in cache invalidation logic to handle relative paths and non-existent paths more robustly.
- Fixed variable shadowing bug in grep's `match_ext` method where extension parameter was compared against itself.
- Added early return optimization in glob when `maxResults` is zero to avoid unnecessary filesystem scanning.
- Refactored filesystem scan cache integration to use pre-scanned entries from fs_cache module instead of manual directory walking in grep.rs.
- Extracted filesystem scan cache invalidation helpers into dedicated fs-cache-invalidation.ts module with three functions: invalidateFsScanAfterWrite, invalidateFsScanAfterDelete, and invalidateFsScanAfterRename.
- Centralized file mention discovery profile configuration into getMentionCandidateDiscoveryProfile() function for improved maintainability.
- Added comprehensive documentation of filesystem-scan cache architecture contract including cache key specifications, TTL policies, and invalidation patterns.
- Updated CHANGELOG.md to document filesystem scan cache invalidation helpers and named discovery profile for file mention candidates.
- Extracted shared fs_cache.rs from glob.rs: global TTL policy (env-configurable),
cache-aware scanning, empty-result fast recheck (~200ms), explicit invalidation API
- Moved fuzzyFind from grep.rs into dedicated fd.rs module using shared scan cache
- Removed per-call cacheTtlMs from GlobOptions and FuzzyFindOptions (global policy)
- Added invalidateFsScanCache NAPI export, wired into write/edit tools after mutations
- Cleaned up TS callers: file-mentions, autocomplete, tests no longer own cache semantics
- Added PTY (pseudo-terminal) backed interactive command execution with streaming output support via PtySession class in pi-natives.
- Added PtyStartOptions and PtyRunResult types to configure and report PTY session execution status.
- Added write(), resize(), and kill() methods to PtySession for interactive control of running commands.
- Added interactive bash execution via PTY with real-time terminal rendering and input forwarding in bash-interactive tool.
- Added --no-pty CLI flag and PI_NO_PTY environment variable to disable PTY-based interactive bash execution.
- Added bash.virtualTerminal setting to control PTY-backed interactive execution behavior.
- Added zombie process prevention by tracking reap state and implementing Drop trait to ensure processes are properly cleaned up.
- Enabled kill_on_drop for tokio child processes to automatically terminate processes when handles are dropped.
- Improved process termination logic to check reap state before attempting kill operations and properly track completion.
- Added SAFETY comments documenting unsafe block invariants in process child collection.
- Refactored nested if statement to use let-else guard clause pattern in OS distro detection.
- Added macOS marketing name detection to system information collection for both Rust and TypeScript implementations.
- Changed system info functions to return optional values instead of fallback strings, improving data accuracy.
- Refactored GPU caching to be independent from other system info, reducing unnecessary cache invalidation.
- Updated environment info collection to filter out undefined values, providing cleaner system prompt output.
- Enhanced skipped file messages to include file size information for better user visibility.
- Updated auto-read skip messages to display actual file size when files are too large to process.
- Inlined MAX_CLI_TEXT_BYTES calculation for improved code clarity.
- Fixed bash tool hanging with background jobs by implementing timeout-based cancellation and draining stdout/stderr pipes instead of waiting indefinitely for EOF.
- Fixed crash when auto-reading large @mentions by adding file size validation (5MB for text, 25MB for images) before reading file contents.
- Prevented out-of-memory issues by skipping files exceeding size limits and displaying file size information in UI for skipped files.
- Added GB file size formatting support to handle very large files in human-readable format.
- Added file size display in UI for skipped files to inform users why files were not included.
- Added test case verifying bash executor returns correctly when command spawns background jobs.
- Fixed timeout command not properly cancelling child processes by adding explicit cancellation token handling and graceful shutdown wait.
- Added child process cancellation token creation and propagation to command execution parameters.
- Added explicit child process cancellation and 2-second graceful shutdown timeout when timeout expires or parent is cancelled.
- Fixed cursor display position in Input component during horizontal scrolling by calculating position relative to visible text window instead of using fixed halfWidth value.
- Fixed full-screen redraws optimization by tracking previous rendered line count and avoiding unnecessary full redraws when changes occur above the viewport.
- Fixed scrollback clearing behavior by removing scrollback clear sequence (3J) and only clearing screen content, preventing unintended terminal scroll events.
- Fixed OSC 52 clipboard emission to only occur in real terminal environments (TTY), preventing unnecessary output in piped or headless contexts.
- Fixed error handling for OSC 52 clipboard writes to gracefully handle EPIPE errors when stdout is closed or piped to processes that exit early.