fix(tools/grep, tools/glob): use Node-safe subprocess streaming (#3919)
OpenCode Desktop v1.14.41+ runs OMO inside a Node.js utility process. The previous `new Response(proc.stdout).text()` call is Bun-/Web-API-specific and crashed the Desktop sidecar on Windows when grep/glob were invoked. Switch glob/grep cli to the new process-stream-reader + search-process-output helpers. Behavior on Bun and CLI/Linux/macOS is unchanged. ripgrep auto-download, PowerShell fallback, and rgSemaphore are preserved. Fixes #3919 Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,5 +1,36 @@
|
||||
import { describe, it, expect } from "bun:test"
|
||||
import { buildRgArgs, buildFindArgs, buildPowerShellCommand } from "./cli"
|
||||
import { describe, it, expect, mock } from "bun:test"
|
||||
import { Writable } from "node:stream"
|
||||
import type { SpawnOptions, SpawnedProcess } from "../../shared/bun-spawn-shim"
|
||||
import { buildRgArgs, buildFindArgs, buildPowerShellCommand, runRgFiles } from "./cli"
|
||||
|
||||
function createTextStream(text: string): ReadableStream<Uint8Array> {
|
||||
return new ReadableStream<Uint8Array>({
|
||||
start(controller) {
|
||||
if (text.length > 0) {
|
||||
controller.enqueue(new TextEncoder().encode(text))
|
||||
}
|
||||
controller.close()
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
function createSpawnedProcess(exitCode: number, stdout = "", stderr = ""): SpawnedProcess {
|
||||
return {
|
||||
exitCode,
|
||||
exited: Promise.resolve(exitCode),
|
||||
stdout: createTextStream(stdout),
|
||||
stderr: createTextStream(stderr),
|
||||
stdin: new Writable({
|
||||
write(_chunk, _encoding, callback) {
|
||||
callback()
|
||||
},
|
||||
}),
|
||||
pid: 3919,
|
||||
kill() {},
|
||||
ref() {},
|
||||
unref() {},
|
||||
}
|
||||
}
|
||||
|
||||
describe("buildRgArgs", () => {
|
||||
// given default options (no hidden/follow specified)
|
||||
@@ -166,4 +197,32 @@ describe("buildPowerShellCommand", () => {
|
||||
const command = args.join(" ")
|
||||
expect(command).toContain("test''s.ts")
|
||||
})
|
||||
|
||||
it("uses LiteralPath so fallback paths are not wildcard-expanded (#3919)", () => {
|
||||
const args = buildPowerShellCommand({ pattern: "*.ts", paths: ["C:\\repo[1]"] })
|
||||
const command = args.join(" ")
|
||||
expect(args[0]).toBe("powershell.exe")
|
||||
expect(command).toContain("Get-ChildItem -LiteralPath 'C:\\repo[1]'")
|
||||
})
|
||||
})
|
||||
|
||||
describe("runRgFiles", () => {
|
||||
it("#given empty stdout #when rg exits successfully #then returns an empty result", async () => {
|
||||
const spawnMock = mock((_command: string[], _options?: SpawnOptions): SpawnedProcess =>
|
||||
createSpawnedProcess(0)
|
||||
)
|
||||
|
||||
const result = await runRgFiles(
|
||||
{ pattern: "*.ts", paths: ["."], timeout: 1000 },
|
||||
{ path: "rg", backend: "rg" },
|
||||
spawnMock
|
||||
)
|
||||
|
||||
expect(result).toEqual({
|
||||
files: [],
|
||||
totalFiles: 0,
|
||||
truncated: false,
|
||||
})
|
||||
expect(spawnMock).toHaveBeenCalled()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user