Repository navigation
Conversation
…text The Step find adapter dropped every native output line starting with "[" or "WARNING:" to remove the notices the find tool appends. A narrowed search returns paths relative to the search root, so `[id]/page.tsx` arrives with the bracket in the first position and was discarded as a notice: `find_files` reported `(no matches)` and `matchedFiles: 0` for a directory the backend had already resolved. The find tool now reports its match list in `details.files`, and the adapter reads that list instead of parsing rendered text. Text parsing stays as a fallback for injected backends that report no list, and it now removes the notice block by shape — one bracketed block after a blank line — rather than by line prefix.
li-xiu-qi
requested review from
MelodyVAR,
Uking-xxx,
ZouR-Ma and
liuedcson
as code owners
October 20, 2026 18:23
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
find_filesloses valid matches whenever the first character of a returned path is[. Next.js App Router names dynamic segments that way ([id],[...slug],[[...slug]]), so withroutes/[id]/page.tsxpresent:{ "pattern": "*.tsx", "path": "routes" }returns
(no matches)even though the native find backend resolved the file.search_fileson the same directory returns it correctly, which is the clearest way to see that this is one tool's gap rather than a missing capability.Trigger is a narrowed search. Paths come back relative to the search root, so
path: "routes"yields[id]/page.tsxwith the bracket in first position. Searching from the repository root yieldsroutes/[id]/page.tsx, and the bug does not appear — which is why it survives casual use.Root cause.
stripNativeFindNotices(packages/coding-agent/src/step/tool-profile.ts) dropped every line starting with[orWARNING:to remove the notices the find tool appends. Those notices are themselves a bracketed block appended at the end of the output (find.ts::finalizeOutputappends"\n\n[" + notices.join(". ") + "]"). A path and a notice therefore share the same first character, and a per-line prefix test cannot separate them.Two distinct losses. When the directory also holds ordinary files, the bracket routes vanish silently and
matchedFilesunder-reports — 1 instead of 3 in the repro below — so the model is told the directory has fewer files than it does. When every match is bracket-prefixed, the result collapses to(no matches), and the match is lost outright rather than shown wrong.Changes
The find tool already knows the resolved paths; the adapter now reads them instead of inferring them from rendered text.
packages/coding-agent/src/core/tools/find.tsFindToolDetailsgains optionalfiles?: string[], filled infinalizeOutputfrom the same array the rendered text is built from, so the two cannot disagree.detailsis local metadata and is not sent to the model, so the model-visible output is unchanged.files: []. That distinguishes "the search genuinely matched nothing" from "this backend reports no list" (undefined), which is what lets a consumer trust an empty result instead of re-parsing text.packages/coding-agent/src/step/tool-profile.tsfindFilesFromDetailsreadsdetails.files;executeFindFilesuses it first.stripNativeFindNoticesbecomes the fallback for injected backends that report no list, and now removes the notice by shape — one bracketed block after a blank line, at the end of the output — instead of dropping lines by prefix. Bracket-prefixed paths and paths beginning withWARNING:both survive.packages/coding-agent/test/step-tool-profile.test.ts[id],[...slug], and[[...slug]]route directories, and assertsmatchedFiles/returnedFiles.WARNING:is not discarded (skipped on Windows, where:is not a legal filename character).Why both layers. The structured list removes inference from the main path; shape-based removal keeps the fallback from guessing by prefix. Only the first would still drop paths for injected backends. Only the second would still be reading data out of text.
Behavior and compatibility
details.filesis a new optional field.backend,resultLimitReached, andtruncationkeep their meaning; the Step-facingmatchedFilesandreturnedFilesare unchanged.WARNING:was previously discarded and is now returned. This cannot occur on Windows (:is not allowed in filenames).details.filesis the native match list and can be longer than the Step-facingreturnedFileswhenmax_resultstruncates. The two are named differently on purpose; neither reinterprets the other.Validation
Repro is a
routes/directory holding[id]/page.tsx,[...slug]/page.tsx, andstatic/page.tsx, queried withfind_files { pattern: "*.tsx", path: "routes", max_results: 10 }. All three are genuine matches, so the correct result is three rows andmatchedFiles: 3.Before (main @ be88ee7) — one row survives, and the count is wrong too:
After (this branch):
The
matchedFiles: 1 → 3part matters as much as the restored rows: the count was telling the model the directory held one file.The new tests fail on
mainwith all three bracket rows missing, and pass with the change.vitest run test/step-tool-profile.test.ts test/find-fallback.test.ts test/suite/regressions/3302-find-path-glob.test.ts test/suite/regressions/3303-find-nested-gitignore.test.ts test/suite/regressions/6104-find-root-relativization.test.ts— 53/53 passednpm run check— passed (biome, tsgo, repository check scripts)tsgo --noEmit— no errorsWARNING:path case is skipped there and runs on platforms where the filename is legal.Limitations