mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-06 08:50:43 +00:00
fix: install ClawHub package dependencies
This commit is contained in:
@@ -36,6 +36,7 @@ Docs: https://docs.openclaw.ai
|
||||
- Web search/Exa: accept `plugins.entries.exa.config.webSearch.baseUrl`, normalize it to the Exa `/search` endpoint, and partition cached results by endpoint. Fixes #54928 and supersedes #54939. Thanks @mrpl327 and @lyfuci.
|
||||
- Web search/MiniMax: include MiniMax Search in the web-search setup flow and let `MINIMAX_API_KEY` participate in MiniMax Search auto-detection. Supersedes #65828. Thanks @Jah-yee.
|
||||
- Plugins/ClawHub: preserve official source-linked trust through archive installs, so OpenClaw can install trusted ClawHub plugin packages that trigger the built-in dangerous-pattern scanner. Thanks @vincentkoc.
|
||||
- Plugins/ClawHub: install package runtime dependencies for archive-backed plugin installs, so ClawHub packages such as WhatsApp load declared dependencies after download. Thanks @vincentkoc.
|
||||
- Providers/LM Studio: allow `models.providers.lmstudio.params.preload: false` to skip OpenClaw's native model-load call so LM Studio JIT loading, idle TTL, and auto-evict can own model lifecycle. Fixes #75921. Thanks @garyd9.
|
||||
- Telegram: inherit the process DNS result order for Bot API transport and downgrade recovered sticky IPv4 fallback promotions to debug logs, while keeping pinned-IP escalation warnings visible. Fixes #75904. Thanks @highfly-hi and @neeravmakwana.
|
||||
- Sessions: keep durable external conversation pointers, including group and thread-scoped chat sessions, out of age, count, and disk-budget maintenance eviction while still allowing synthetic runtime entries to age out. Fixes #58088. Thanks @drinkflav.
|
||||
|
||||
@@ -622,7 +622,7 @@ beforeEach(() => {
|
||||
});
|
||||
|
||||
describe("installPluginFromArchive", () => {
|
||||
it("does not run npm for package archive runtime dependencies", async () => {
|
||||
it("installs package archive runtime dependencies", async () => {
|
||||
const result = await installArchivePackageAndReturnResult({
|
||||
packageJson: {
|
||||
name: "archive-with-deps",
|
||||
@@ -635,7 +635,12 @@ describe("installPluginFromArchive", () => {
|
||||
});
|
||||
|
||||
expect(result.ok).toBe(true);
|
||||
expect(vi.mocked(runCommandWithTimeout)).not.toHaveBeenCalled();
|
||||
expect(vi.mocked(runCommandWithTimeout)).toHaveBeenCalledWith(
|
||||
expect.arrayContaining(["npm", "install"]),
|
||||
expect.objectContaining({
|
||||
cwd: expect.stringContaining(".openclaw-install-stage-"),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("installs scoped archives, rejects duplicate installs, and allows updates", async () => {
|
||||
|
||||
@@ -178,6 +178,13 @@ function buildDirectoryInstallResult(params: {
|
||||
};
|
||||
}
|
||||
|
||||
function hasPackageRuntimeDependencies(manifest: PackageManifest): boolean {
|
||||
return (
|
||||
Object.keys(manifest.dependencies ?? {}).length > 0 ||
|
||||
Object.keys(manifest.optionalDependencies ?? {}).length > 0
|
||||
);
|
||||
}
|
||||
|
||||
function buildBlockedInstallResult(params: {
|
||||
blocked: NonNullable<NonNullable<InstallSecurityScanResult>["blocked"]>;
|
||||
}): Extract<InstallPluginResult, { ok: false }> {
|
||||
@@ -560,6 +567,7 @@ type ValidatedPackagePlugin = {
|
||||
manifestName?: string;
|
||||
version?: string;
|
||||
extensions: string[];
|
||||
hasRuntimeDependencies: boolean;
|
||||
peerDependencies: Record<string, string>;
|
||||
};
|
||||
|
||||
@@ -719,6 +727,7 @@ async function validatePackagePluginInstallSource(params: {
|
||||
manifestName: pkgName || undefined,
|
||||
version: typeof manifest.version === "string" ? manifest.version : undefined,
|
||||
extensions,
|
||||
hasRuntimeDependencies: hasPackageRuntimeDependencies(manifest),
|
||||
peerDependencies: manifest.peerDependencies ?? {},
|
||||
},
|
||||
};
|
||||
@@ -855,8 +864,9 @@ async function installPluginFromPackageDir(
|
||||
mode: preparedTarget.effectiveMode,
|
||||
dryRun,
|
||||
copyErrorPrefix: "failed to copy plugin",
|
||||
hasDeps: false,
|
||||
depsLogMessage: "",
|
||||
hasDeps:
|
||||
plugin.hasRuntimeDependencies && params.installPolicyRequest?.kind === "plugin-archive",
|
||||
depsLogMessage: "Installing plugin dependencies…",
|
||||
nameEncoder: encodePluginInstallDirName,
|
||||
afterInstall: async (installedDir) => {
|
||||
return await scanAndLinkInstalledPackage({
|
||||
|
||||
Reference in New Issue
Block a user