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:
YeonGyu-Kim
2026-05-22 20:40:06 +09:00
parent 4ea7562f50
commit d17b2127f2
4 changed files with 183 additions and 62 deletions
+61 -2
View File
@@ -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()
})
})