Explorar el Código

fix(core): report truncated glob results (#38631)

Aiden Cline hace 2 semanas
padre
commit
c64d813347
Se han modificado 2 ficheros con 23 adiciones y 12 borrados
  1. 18 10
      packages/core/src/tool/glob.ts
  2. 5 2
      packages/core/test/tool-search.test.ts

+ 18 - 10
packages/core/src/tool/glob.ts

@@ -25,11 +25,16 @@ export const Input = Schema.Struct({
 })
 
 export const Output = Schema.Array(FileSystem.Entry)
-type ModelOutput = typeof Output.Encoded
+type EncodedOutput = typeof Output.Encoded
 
 /** Format raw search results into the concise line-oriented output models expect. */
-export const toModelOutput = (output: ModelOutput) => {
-  const lines = output.length === 0 ? ["No files found"] : output.map((item) => item.path)
+export const toModelContent = (entries: EncodedOutput, truncated = false) => {
+  const lines = entries.length === 0 ? ["No files found"] : entries.map((item) => item.path)
+  if (truncated)
+    lines.push(
+      "",
+      `(Results are truncated: showing first ${entries.length} results. Consider using a more specific path or pattern.)`,
+    )
   return lines.join("\n")
 }
 
@@ -74,11 +79,12 @@ export const Plugin = {
                       Effect.fail(new ToolFailure({ message: `Search path does not exist: ${input.path ?? "."}` })),
                     ),
                   )
-                return yield* ripgrep
+                const limit = input.limit ?? FileSystem.DEFAULT_SEARCH_LIMIT
+                const entries = yield* ripgrep
                   .glob({
                     cwd,
                     pattern: input.pattern,
-                    limit: input.limit ?? FileSystem.DEFAULT_SEARCH_LIMIT,
+                    limit: limit + 1,
                   })
                   .pipe(
                     Effect.map((result) =>
@@ -90,13 +96,15 @@ export const Plugin = {
                       ),
                     ),
                   )
+                return { entries: entries.slice(0, limit), truncated: entries.length > limit }
               }).pipe(
-                Effect.map((output) => ({
-                  output,
-                  content: toModelOutput(
-                    output.map((entry) => ({ ...entry, path: path.resolve(location.directory, entry.path) })),
+                Effect.map((result) => ({
+                  output: result.entries,
+                  content: toModelContent(
+                    result.entries.map((entry) => ({ ...entry, path: path.resolve(location.directory, entry.path) })),
+                    result.truncated,
                   ),
-                  metadata: { count: output.length },
+                  metadata: { count: result.entries.length, truncated: result.truncated },
                 })),
                 Effect.mapError((error) =>
                   error instanceof ToolFailure

+ 5 - 2
packages/core/test/tool-search.test.ts

@@ -86,13 +86,16 @@ describe("search tools", () => {
               const glob = yield* executeTool(registry, call("glob", { pattern: "*" }))
               const grep = yield* executeTool(registry, call("grep", { pattern: "needle" }))
 
-              expect(glob.metadata).toEqual({ count: FileSystem.DEFAULT_SEARCH_LIMIT })
+              expect(glob.metadata).toEqual({ count: FileSystem.DEFAULT_SEARCH_LIMIT, truncated: true })
               expect(grep.metadata).toEqual({ matches: FileSystem.DEFAULT_SEARCH_LIMIT })
               expect(glob.content).toHaveLength(1)
               expect(grep.content).toHaveLength(1)
               const globText = glob.content?.[0]?.type === "text" ? glob.content[0].text : ""
               const grepText = grep.content?.[0]?.type === "text" ? grep.content[0].text : ""
-              expect(globText.split("\n")).toHaveLength(FileSystem.DEFAULT_SEARCH_LIMIT)
+              expect(globText.split("\n")).toHaveLength(FileSystem.DEFAULT_SEARCH_LIMIT + 2)
+              expect(globText).toEndWith(
+                `(Results are truncated: showing first ${FileSystem.DEFAULT_SEARCH_LIMIT} results. Consider using a more specific path or pattern.)`,
+              )
               expect(grepText).toStartWith(`Found ${FileSystem.DEFAULT_SEARCH_LIMIT} matches\n`)
             }),
           )