
























@@ -1,4 +1,5 @@
11import { spawn } from "node:child_process";
2+import { statSync } from "node:fs";
23import { materializeWindowsSpawnProgram, resolveWindowsSpawnProgram } from "./windows-spawn.js";
3445export type CliSpawnInvocation = {
@@ -8,11 +9,26 @@ export type CliSpawnInvocation = {
89windowsHide?: boolean;
910};
101111-export type QmdBinaryAvailability = {
12-available: boolean;
13-error?: string;
12+export type QmdBinaryUnavailableReason = "binary" | "workspace-cwd";
13+14+export type QmdBinaryUnavailable = {
15+available: false;
16+/**
17+ * Optional for source compatibility with older plugin SDK callers that
18+ * returned only `{ available: false, error }`.
19+ */
20+reason?: QmdBinaryUnavailableReason;
21+error: string;
1422};
152324+export type QmdBinaryAvailability = { available: true } | QmdBinaryUnavailable;
25+26+export function resolveQmdBinaryUnavailableReason(
27+result: QmdBinaryUnavailable,
28+): QmdBinaryUnavailableReason {
29+return result.reason ?? "binary";
30+}
31+1632export function resolveCliSpawnInvocation(params: {
1733command: string;
1834args: string[];
@@ -45,7 +61,13 @@ export async function checkQmdBinaryAvailability(params: {
4561packageName: "qmd",
4662});
4763} catch (err) {
48-return { available: false, error: formatQmdAvailabilityError(err) };
64+return { available: false, reason: "binary", error: formatQmdAvailabilityError(err) };
65+}
66+67+const cwd = params.cwd ?? process.cwd();
68+const cwdError = validateQmdProbeCwd(cwd);
69+if (cwdError) {
70+return cwdError;
4971}
50725173return await new Promise((resolve) => {
@@ -64,7 +86,7 @@ export async function checkQmdBinaryAvailability(params: {
64866587const child = spawn(spawnInvocation.command, spawnInvocation.argv, {
6688env: params.env,
67-cwd: params.cwd ?? process.cwd(),
89+ cwd,
6890shell: spawnInvocation.shell,
6991windowsHide: spawnInvocation.windowsHide,
7092stdio: "ignore",
@@ -73,12 +95,13 @@ export async function checkQmdBinaryAvailability(params: {
7395child.kill("SIGKILL");
7496finish({
7597available: false,
98+reason: "binary",
7699error: `spawn ${params.command} timed out after ${params.timeoutMs ?? 2_000}ms`,
77100});
78101}, params.timeoutMs ?? 2_000);
7910280103child.once("error", (err) => {
81-finish({ available: false, error: formatQmdAvailabilityError(err) });
104+finish({ available: false, reason: "binary", error: formatQmdAvailabilityError(err) });
82105});
83106child.once("spawn", () => {
84107didSpawn = true;
@@ -94,6 +117,33 @@ export async function checkQmdBinaryAvailability(params: {
94117});
95118}
96119120+function validateQmdProbeCwd(cwd: string): QmdBinaryAvailability | null {
121+try {
122+const stat = statSync(cwd);
123+if (!stat.isDirectory()) {
124+return {
125+available: false,
126+reason: "workspace-cwd",
127+error: `workspace directory is not a directory: ${cwd}`,
128+};
129+}
130+return null;
131+} catch (err) {
132+if (typeof err === "object" && err && "code" in err && err.code === "ENOENT") {
133+return {
134+available: false,
135+reason: "workspace-cwd",
136+error: `workspace directory missing: ${cwd}`,
137+};
138+}
139+return {
140+available: false,
141+reason: "workspace-cwd",
142+error: `workspace directory unavailable: ${cwd} (${formatQmdAvailabilityError(err)})`,
143+};
144+}
145+}
146+97147export async function runCliCommand(params: {
98148commandSummary: string;
99149spawnInvocation: CliSpawnInvocation;
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。