mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-09 07:00:44 +00:00
fix: explain missing git during plugin install
This commit is contained in:
@@ -1096,6 +1096,34 @@ describe("plugins cli install", () => {
|
||||
expect(runtimeErrors.at(-1)).toContain("npm install failed");
|
||||
});
|
||||
|
||||
it("adds a Git PATH hint when npm plugin dependency install cannot spawn git", async () => {
|
||||
loadConfig.mockReturnValue({} as OpenClawConfig);
|
||||
installPluginFromNpmSpec.mockResolvedValue({
|
||||
ok: false,
|
||||
error: [
|
||||
"npm install failed:",
|
||||
"npm error code ENOENT",
|
||||
"npm error syscall spawn git",
|
||||
"npm error path git",
|
||||
].join("\n"),
|
||||
});
|
||||
installHooksFromNpmSpec.mockResolvedValue({
|
||||
ok: false,
|
||||
error: "package.json missing openclaw.hooks",
|
||||
});
|
||||
|
||||
await expect(
|
||||
runPluginsCommand(["plugins", "install", "npm:@openclaw/whatsapp"]),
|
||||
).rejects.toThrow("__exit__:1");
|
||||
|
||||
expect(installPluginFromClawHub).not.toHaveBeenCalled();
|
||||
expect(runtimeErrors.at(-1)).toContain(
|
||||
"one of this plugin's npm dependencies is fetched from a git URL",
|
||||
);
|
||||
expect(runtimeErrors.at(-1)).toContain("winget install --id Git.Git -e");
|
||||
expect(runtimeErrors.at(-1)).toContain("Also not a valid hook pack");
|
||||
});
|
||||
|
||||
it("does not resolve npm: prefixed bundled plugin ids through bundled installs", async () => {
|
||||
loadConfig.mockReturnValue({ plugins: { load: { paths: [] } } } as OpenClawConfig);
|
||||
installPluginFromNpmSpec.mockResolvedValue({
|
||||
|
||||
@@ -176,16 +176,36 @@ export function formatPluginInstallWithHookFallbackError(
|
||||
pluginError: string,
|
||||
hookError: string,
|
||||
): string {
|
||||
const formattedPluginError = formatPluginInstallAttemptError(pluginError);
|
||||
const formattedHookError = formatPluginInstallAttemptError(hookError);
|
||||
if (/plugin already exists: .+ \(delete it first\)/.test(pluginError)) {
|
||||
return `${pluginError}\nUse \`openclaw plugins update <id-or-npm-spec>\` to upgrade the tracked plugin, or rerun install with \`--force\` to replace it.`;
|
||||
return `${formattedPluginError}\nUse \`openclaw plugins update <id-or-npm-spec>\` to upgrade the tracked plugin, or rerun install with \`--force\` to replace it.`;
|
||||
}
|
||||
if (
|
||||
pluginError.startsWith("Invalid extensions directory:") ||
|
||||
pluginError === "Invalid path: must stay within extensions directory"
|
||||
) {
|
||||
return pluginError;
|
||||
return formattedPluginError;
|
||||
}
|
||||
return `${pluginError}\nAlso not a valid hook pack: ${hookError}`;
|
||||
return `${formattedPluginError}\nAlso not a valid hook pack: ${formattedHookError}`;
|
||||
}
|
||||
|
||||
const MISSING_GIT_FOR_NPM_DEPENDENCY_HINT =
|
||||
"Git is required because one of this plugin's npm dependencies is fetched from a git URL, but `git` was not found on PATH. Install Git and rerun the install. On Windows, use `winget install --id Git.Git -e` or add a portable Git `bin` directory to PATH.";
|
||||
|
||||
function formatPluginInstallAttemptError(error: string): string {
|
||||
if (!isMissingGitForNpmDependencyError(error)) {
|
||||
return error;
|
||||
}
|
||||
if (error.includes(MISSING_GIT_FOR_NPM_DEPENDENCY_HINT)) {
|
||||
return error;
|
||||
}
|
||||
return `${error}\n\n${MISSING_GIT_FOR_NPM_DEPENDENCY_HINT}`;
|
||||
}
|
||||
|
||||
function isMissingGitForNpmDependencyError(error: string): boolean {
|
||||
const normalized = normalizeLowercaseStringOrEmpty(error);
|
||||
return /\bspawn\s+git\b/u.test(normalized) && /\benoent\b/u.test(normalized);
|
||||
}
|
||||
|
||||
export function logHookPackRestartHint(runtime: RuntimeEnv = defaultRuntime) {
|
||||
|
||||
Reference in New Issue
Block a user