feat(glob): add brace expansion, fix backslash escaping, and lower match cap#282
Conversation
- add brace expansion support for glob patterns with up to 64 sub-pattern cap\n- remove up-front rejection of pure-wildcard and **/ prefix patterns; rely on 100-match cap\n- fix backslash escape handling in globPatternToRegex and inside character classes\n- include matched count in truncation messages\n- show glob pattern, path, and include_dirs in TUI tool-call headers
🦋 Changeset detectedLatest commit: f4aa305 The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
commit: |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cf9bd45811
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| case '\\': { | ||
| if (i + 1 < pattern.length) { | ||
| const next = pattern[i + 1]; | ||
| regex += next.replaceAll(/[{}()+.\\[\]^$|]/g, '\\$&'); |
There was a problem hiding this comment.
Escape escaped wildcard metacharacters
When a glob pattern uses a backslash to match a literal wildcard, e.g. \*.ts or \?name, this branch appends the raw */? into the regex because the escape set omits those regex metacharacters. That makes new RegExp('^*$') / new RegExp('^?$') throw “Nothing to repeat”, so kaos.glob errors instead of matching files whose names literally contain * or ?; include * and ? in the escaped-character regex here.
Useful? React with 👍 / 👎.
| const seen = new Set<string>(); | ||
| const entries: Array<{ path: string; mtime: number }> = []; | ||
| const YIELD_SAFETY_CAP = MAX_MATCHES * 2; | ||
| const YIELD_SAFETY_CAP = MAX_MATCHES * 2 * subPatterns.length; |
There was a problem hiding this comment.
Don’t truncate file-only glob results on skipped directories
When include_dirs is false and the pattern yields directories before files (for example Glob with pattern: "**" in a directory-heavy workspace), this raw-yield cap is now only 200 for a single subpattern and counts directories that are filtered out later. In that case the loop can stop with a truncation header and few or no returned files even though matching files exist below; keep the cycle-safety cap independent of the 100 returned-file limit or count it after filtered directories are skipped.
Useful? React with 👍 / 👎.
Summary
This PR adds brace expansion support to the Glob tool, fixes backslash escaping in glob patterns, and replaces up-front rejection of broad patterns with a lower match-count cap.
1. Add brace expansion support to Glob tool
Problem: The Glob tool previously rejected brace expansion patterns (e.g.,
*.{ts,tsx},{src,test}/**) outright, forcing callers to manually split into separate calls. This added friction and wasted caller context.What was done:
expandBraces()that supports cartesian products and one level of nesting.MAX_BRACE_EXPANSIONS = 64cap to prevent pathological fan-out.glob.md) to document brace expansion support.2. Fix backslash escaping in glob patterns
Problem: Backslash (
\) was not treated as a proper escape character inglobPatternToRegex, and trailing backslashes inside character classes like[abc\\]could produce invalid regexes.What was done:
kaos/src/internal.tsthat advances past the escaped character.]to keep the regex valid.packages/kaos/test/internal.test.ts.3. Replace pre-rejection with match-count cap
Problem: Patterns starting with
**/or consisting of pure wildcards were hard-rejected before any walk happened. This was overly restrictive and inconsistent with other implementations.What was done:
startsWithDoubleStarPrefix(),isPureWildcard(), andcontainsBraceExpansion()pre-rejections.MAX_MATCHESfrom 1000 to 100 — the cap itself is now the single safety rail.Checklist
gen-changesetsskill.gen-docsskill.