Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions src/core/environment/__tests__/getEnvironmentDetails.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -446,4 +446,22 @@ describe("getEnvironmentDetails", () => {

expect(getGitStatus).toHaveBeenCalledWith(mockCwd, 5)
})

// Regression test for https://github.com/Zoo-Code-Org/Zoo-Code/issues/1024
// When ripgrep cannot be found (e.g. @vscode/ripgrep >=1.18 platform layout on
// Windows), listFiles throws "Could not find ripgrep binary". getEnvironmentDetails
// must not propagate this — the task should proceed to the API call, not hang at 0%.
it("should degrade gracefully when listFiles rejects with an Error", async () => {
;(listFiles as Mock).mockRejectedValue(new Error("Could not find ripgrep binary"))

const result = await getEnvironmentDetails(mockCline as Task, true)
expect(result).toContain("File listing unavailable: Could not find ripgrep binary")
})

it("should degrade gracefully when listFiles rejects with a non-Error value", async () => {
;(listFiles as Mock).mockRejectedValue("unexpected string rejection")

const result = await getEnvironmentDetails(mockCline as Task, true)
expect(result).toContain("File listing unavailable: unexpected string rejection")
})
})
28 changes: 16 additions & 12 deletions src/core/environment/getEnvironmentDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -241,18 +241,22 @@ export async function getEnvironmentDetails(cline: Task, includeFileDetails: boo
if (maxFiles === 0) {
details += "(Workspace files context disabled. Use list_files to explore if needed.)"
} else {
const [files, didHitLimit] = await listFiles(cline.cwd, true, maxFiles)
const { showRooIgnoredFiles = false } = state ?? {}

const result = formatResponse.formatFilesList(
cline.cwd,
files,
didHitLimit,
cline.rooIgnoreController,
showRooIgnoredFiles,
)

details += result
try {
const [files, didHitLimit] = await listFiles(cline.cwd, true, maxFiles)
const { showRooIgnoredFiles = false } = state ?? {}

const result = formatResponse.formatFilesList(
cline.cwd,
files,
didHitLimit,
cline.rooIgnoreController,
showRooIgnoredFiles,
)

details += result
} catch (error) {
details += `(File listing unavailable: ${error instanceof Error ? error.message : String(error)})`
}
}
}
}
Expand Down
46 changes: 46 additions & 0 deletions src/services/ripgrep/__tests__/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,50 @@ describe("getBinPath", () => {

expect(await getBinPath(appRoot)).toBeUndefined()
})

// Regression test for https://github.com/Zoo-Code-Org/Zoo-Code/issues/1024
// VS Code 1.130+ ships @vscode/ripgrep >=1.18, where the binary lives in a
// platform-specific optional package (e.g. @vscode/ripgrep-win32-x64).
// None of the previous candidate paths matched this layout.
it("resolves ripgrep from the @vscode/ripgrep >=1.18 platform-package layout", async () => {
const arch = process.env.npm_config_arch || process.arch
const rg = path.join(appRoot, `node_modules/@vscode/ripgrep-${process.platform}-${arch}/bin`, binName)
mockFileExists.mockImplementation(async (p: string) => p === rg)

expect(await getBinPath(appRoot)).toBe(rg)
})

it("resolves ripgrep from the unpacked @vscode/ripgrep >=1.18 platform-package layout", async () => {
const arch = process.env.npm_config_arch || process.arch
const rg = path.join(
appRoot,
`node_modules.asar.unpacked/@vscode/ripgrep-${process.platform}-${arch}/bin`,
binName,
)
mockFileExists.mockImplementation(async (p: string) => p === rg)

expect(await getBinPath(appRoot)).toBe(rg)
})

it("respects npm_config_arch when selecting the platform package", async () => {
const overrideArch = "x64"
const original = process.env.npm_config_arch
process.env.npm_config_arch = overrideArch
try {
const rg = path.join(
appRoot,
`node_modules/@vscode/ripgrep-${process.platform}-${overrideArch}/bin`,
binName,
)
mockFileExists.mockImplementation(async (p: string) => p === rg)

expect(await getBinPath(appRoot)).toBe(rg)
} finally {
if (original === undefined) {
delete process.env.npm_config_arch
} else {
process.env.npm_config_arch = original
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
})
})
12 changes: 9 additions & 3 deletions src/services/ripgrep/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,9 @@ export function truncateLine(line: string, maxLength: number = MAX_LINE_LENGTH):
* resolution) and the diagnostic command (existence report for all paths).
*/
export function ripgrepCandidatePaths(vscodeAppRoot: string): readonly string[] {
// Read at call time so process.env.npm_config_arch overrides take effect,
// matching @vscode/ripgrep's own arch selection logic.
const platformPkg = `@vscode/ripgrep-${process.platform}-${process.env.npm_config_arch || process.arch}`
return [
path.join(vscodeAppRoot, "node_modules/@vscode/ripgrep/bin/", binName),
path.join(vscodeAppRoot, "node_modules/vscode-ripgrep/bin", binName),
Expand All @@ -101,15 +104,18 @@ export function ripgrepCandidatePaths(vscodeAppRoot: string): readonly string[]
`node_modules.asar.unpacked/@vscode/ripgrep-universal/${ripgrepUniversalBinDir}`,
binName,
),
// @vscode/ripgrep >=1.18 (VS Code 1.130+): binary lives in a platform-specific optional package.
path.join(vscodeAppRoot, `node_modules/${platformPkg}/bin`, binName),
path.join(vscodeAppRoot, `node_modules.asar.unpacked/${platformPkg}/bin`, binName),
]
}

/**
* Get the path to the ripgrep binary shipped inside the VS Code installation.
*
* Both the long-standing `@vscode/ripgrep` layout and the newer
* `@vscode/ripgrep-universal` layout are checked — the latter is what VS Code
* Insiders' staged-install builds use (see microsoft/vscode#252063).
* Probes all known layouts: classic @vscode/ripgrep, @vscode/ripgrep-universal
* (VS Code Insiders staged-install), and the @vscode/ripgrep >=1.18
* platform-package layout used by VS Code 1.130+.
*
* Returns `undefined` when ripgrep cannot be located.
*/
Expand Down
Loading