refactor: make executable resolution async and centralize spawn

- Rename findExecutable → findExecutableSync, add async findExecutable
  that uses promisified execFile instead of execFileSync
- Simplify Windows PATH resolution: rely on inherited env from Explorer
  instead of shelling out to PowerShell for registry PATH entries
- Add spawnProcess() helper that centralizes Windows shell/quoting concerns
- Update all agent providers and consumers to use async executable resolution
- Add windowsHide: true across all Windows child process calls
This commit is contained in:
Mohamed Boudra
2026-04-08 23:24:43 +07:00
parent fc667d6312
commit dace4f862f
25 changed files with 449 additions and 522 deletions
@@ -7,19 +7,19 @@ import {
} from "./provider-launch-config.js";
describe("resolveProviderCommandPrefix", () => {
test("uses resolved default command in default mode", () => {
test("uses resolved default command in default mode", async () => {
const resolveDefault = vi.fn(() => "/usr/local/bin/claude");
const resolved = resolveProviderCommandPrefix(undefined, resolveDefault);
const resolved = await resolveProviderCommandPrefix(undefined, resolveDefault);
expect(resolveDefault).toHaveBeenCalledTimes(1);
expect(resolved).toEqual({ command: "/usr/local/bin/claude", args: [] });
});
test("appends args in append mode", () => {
test("appends args in append mode", async () => {
const resolveDefault = vi.fn(() => "/usr/local/bin/claude");
const resolved = resolveProviderCommandPrefix(
const resolved = await resolveProviderCommandPrefix(
{
mode: "append",
args: ["--chrome"],
@@ -34,10 +34,10 @@ describe("resolveProviderCommandPrefix", () => {
});
});
test("replaces command in replace mode without resolving default", () => {
test("replaces command in replace mode without resolving default", async () => {
const resolveDefault = vi.fn(() => "/usr/local/bin/claude");
const resolved = resolveProviderCommandPrefix(
const resolved = await resolveProviderCommandPrefix(
{
mode: "replace",
argv: ["docker", "run", "--rm", "my-wrapper"],