


















@@ -2,6 +2,7 @@ import fs from "node:fs/promises";
22import os from "node:os";
33import path from "node:path";
44import { afterEach, beforeEach, describe, expect, it } from "vitest";
5+import { resolveOpenClawPackageRootSync } from "../../infra/openclaw-root.js";
56import { runPluginPayloadSmokeCheck } from "./plugin-payload-validation.js";
6778describe("runPluginPayloadSmokeCheck", () => {
@@ -28,6 +29,25 @@ describe("runPluginPayloadSmokeCheck", () => {
2829}
2930}
303132+function resolveTestHostRoot(): string {
33+const hostRoot = resolveOpenClawPackageRootSync({
34+argv1: process.argv[1],
35+moduleUrl: import.meta.url,
36+cwd: process.cwd(),
37+});
38+expect(hostRoot).toBeTruthy();
39+return hostRoot!;
40+}
41+42+async function linkOpenClawPeerToHost(dir: string): Promise<void> {
43+await fs.mkdir(path.join(dir, "node_modules"), { recursive: true });
44+await fs.symlink(resolveTestHostRoot(), path.join(dir, "node_modules", "openclaw"), "junction");
45+}
46+47+async function resolveRealPath(target: string): Promise<string> {
48+return await fs.realpath(target).catch(() => target);
49+}
50+3151it("reports ok for a record whose package.json + main file exist", async () => {
3252const dir = path.join(tmpRoot, "discord");
3353await writePackage(
@@ -167,6 +187,127 @@ describe("runPluginPayloadSmokeCheck", () => {
167187expect(result.failures).toEqual([]);
168188});
169189190+it("reports a failure when an openclaw peer link is missing", async () => {
191+const dir = path.join(tmpRoot, "codex");
192+await writePackage(
193+dir,
194+{
195+name: "@openclaw/codex",
196+main: "dist/index.js",
197+peerDependencies: { openclaw: ">=2026.5.18-beta.1" },
198+},
199+"export default {};\n",
200+);
201+202+const result = await runPluginPayloadSmokeCheck({
203+records: { codex: { source: "npm", installPath: dir } },
204+env: {},
205+});
206+207+expect(result.failures).toStrictEqual([
208+{
209+pluginId: "codex",
210+installPath: dir,
211+reason: "missing-openclaw-peer-link",
212+detail: `Plugin declares peerDependency "openclaw" but peer link audit failed: missing ${path.join(
213+ dir,
214+ "node_modules",
215+ "openclaw",
216+ )}.`,
217+},
218+]);
219+});
220+221+it("reports a failure when an openclaw peer link is a stale real directory", async () => {
222+const dir = path.join(tmpRoot, "codex");
223+await writePackage(
224+dir,
225+{
226+name: "@openclaw/codex",
227+main: "dist/index.js",
228+peerDependencies: { openclaw: ">=2026.5.18-beta.1" },
229+},
230+"export default {};\n",
231+);
232+const stalePeerDir = path.join(dir, "node_modules", "openclaw");
233+await fs.mkdir(stalePeerDir, { recursive: true });
234+235+const result = await runPluginPayloadSmokeCheck({
236+records: { codex: { source: "npm", installPath: dir } },
237+env: {},
238+});
239+240+expect(result.failures).toHaveLength(1);
241+expect(result.failures[0]).toMatchObject({
242+pluginId: "codex",
243+installPath: dir,
244+reason: "missing-openclaw-peer-link",
245+});
246+expect(result.failures[0]?.detail).toContain(`${stalePeerDir} points to`);
247+expect(result.failures[0]?.detail).toContain(
248+`instead of ${await resolveRealPath(resolveTestHostRoot())}`,
249+);
250+});
251+252+it("reports a failure when an openclaw peer link points at the wrong package root", async () => {
253+const dir = path.join(tmpRoot, "codex");
254+await writePackage(
255+dir,
256+{
257+name: "@openclaw/codex",
258+main: "dist/index.js",
259+peerDependencies: { openclaw: ">=2026.5.18-beta.1" },
260+},
261+"export default {};\n",
262+);
263+const wrongHostRoot = path.join(tmpRoot, "old-openclaw");
264+await fs.mkdir(wrongHostRoot, { recursive: true });
265+await fs.mkdir(path.join(dir, "node_modules"), { recursive: true });
266+await fs.symlink(wrongHostRoot, path.join(dir, "node_modules", "openclaw"), "junction");
267+268+const result = await runPluginPayloadSmokeCheck({
269+records: { codex: { source: "npm", installPath: dir } },
270+env: {},
271+});
272+273+expect(result.failures).toHaveLength(1);
274+expect(result.failures[0]).toMatchObject({
275+pluginId: "codex",
276+installPath: dir,
277+reason: "missing-openclaw-peer-link",
278+});
279+expect(result.failures[0]?.detail).toContain(
280+`${path.join(
281+ dir,
282+ "node_modules",
283+ "openclaw",
284+ )} points to ${await resolveRealPath(wrongHostRoot)} instead of ${await resolveRealPath(
285+ resolveTestHostRoot(),
286+ )}`,
287+);
288+});
289+290+it("accepts an openclaw peer link when it resolves to the host package root", async () => {
291+const dir = path.join(tmpRoot, "codex");
292+await writePackage(
293+dir,
294+{
295+name: "@openclaw/codex",
296+main: "dist/index.js",
297+peerDependencies: { openclaw: ">=2026.5.18-beta.1" },
298+},
299+"export default {};\n",
300+);
301+await linkOpenClawPeerToHost(dir);
302+303+const result = await runPluginPayloadSmokeCheck({
304+records: { codex: { source: "npm", installPath: dir } },
305+env: {},
306+});
307+308+expect(result.failures).toEqual([]);
309+});
310+170311it("reports a failure when an `openclaw.extensions` entry file is missing", async () => {
171312const dir = path.join(tmpRoot, "brave");
172313await writePackage(dir, {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。