Files
fusion/plugins/fusion-plugin-cursor-runtime/src/cli-spawn.ts
gsxdsm 777f64750c FN-7418: fix Cursor CLI Windows shim spawning
Fix Cursor runtime probes to execute Windows cmd and bat shims reliably while preserving diagnostics.

- Run shared Cursor CLI probe and discovery spawns through the shell only on Windows.
- Surface bounded spawn error details in unavailable Cursor probe reasons.
- Cover Windows shell spawning, failure diagnostics, probe, and process-manager behavior with tests.
- Document the Windows PATH shim invocation contract and add a patch changeset.

Files changed:
 .changeset/fn-7418-cursor-cli-windows-cmd.md       |   7 ++
 docs/cursor-cli-contract.md                        |  17 ++++
 .../src/__tests__/cli-spawn.test.ts                | 103 +++++++++++++++++++++
 .../src/__tests__/probe.test.ts                    |  44 ++++++++-
 .../src/__tests__/process-manager.test.ts          |  24 ++++-
 .../fusion-plugin-cursor-runtime/src/cli-spawn.ts  |  41 ++++++--
 plugins/fusion-plugin-cursor-runtime/src/probe.ts  |  14 ++-
 7 files changed, 236 insertions(+), 14 deletions(-)

Fusion-Task-Id: FN-7418
Fusion-Task-Lineage: d689bea7-4676-4190-a60a-f85efab90aba
Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
2026-07-02 11:38:31 -07:00

51 lines
1.9 KiB
TypeScript

import { spawn } from "node:child_process";
function formatSpawnError(error: Error & { code?: unknown }): string {
const code = typeof error.code === "string" ? `${error.code}: ` : "";
return `spawn error: ${code}${error.message}`.trim();
}
export async function runCursorCommand(binary: string, args: string[], timeoutMs: number): Promise<{ code: number | null; stdout: string; stderr: string }> {
return new Promise((resolve) => {
let stdout = "";
let stderr = "";
let settled = false;
let timer: NodeJS.Timeout | undefined;
const finish = (result: { code: number | null; stdout: string; stderr: string }) => {
if (settled) return;
settled = true;
if (timer) clearTimeout(timer);
resolve(result);
};
/*
FNXC:CursorCli 2026-07-02-00:00:
Windows Cursor installers and npm-style shims can expose `cursor-agent.cmd` or `cursor.cmd` on PATH, and Node cannot direct-spawn those batch wrappers without the command shell.
Keep Unix/macOS on direct spawn so only the known Cursor CLI probe/discovery seam uses shell resolution where Windows requires it.
*/
const child = spawn(binary, args, {
stdio: ["ignore", "pipe", "pipe"],
shell: process.platform === "win32",
});
timer = setTimeout(() => {
try { child.kill("SIGKILL"); } catch {
// best effort
}
finish({ code: 124, stdout, stderr });
}, timeoutMs);
child.stdout?.on("data", (c: Buffer) => { stdout += c.toString("utf-8"); });
child.stderr?.on("data", (c: Buffer) => { stderr += c.toString("utf-8"); });
child.once("error", (error: Error & { code?: unknown }) => {
const diagnostic = formatSpawnError(error);
stderr = stderr ? `${stderr}\n${diagnostic}` : diagnostic;
finish({ code: 127, stdout, stderr });
});
child.once("close", (code) => {
finish({ code, stdout, stderr });
});
});
}