
















@@ -4,6 +4,20 @@ import path from "node:path";
44const command = process.argv[2];
55const readJson = (file) => JSON.parse(fs.readFileSync(file, "utf8"));
667+function getInstallRecords() {
8+const indexPath = path.join(process.env.HOME, ".openclaw", "plugins", "installs.json");
9+const index = fs.existsSync(indexPath) ? readJson(indexPath) : {};
10+const configPath = path.join(process.env.HOME, ".openclaw", "openclaw.json");
11+const config = fs.existsSync(configPath) ? readJson(configPath) : {};
12+const allowLegacyCompat = process.env.OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT === "1";
13+if (!allowLegacyCompat && !index.installRecords) {
14+throw new Error("expected modern installRecords in installed plugin index");
15+}
16+return allowLegacyCompat
17+ ? (index.installRecords ?? index.records ?? config.plugins?.installs ?? {})
18+ : (index.installRecords ?? {});
19+}
20+721function recordFixturePluginTrust() {
822const pluginId = process.argv[3];
923const pluginRoot = process.argv[4];
@@ -173,17 +187,7 @@ function assertMarketplaceInstalled() {
173187}
174188175189function assertMarketplaceRecords() {
176-const indexPath = path.join(process.env.HOME, ".openclaw", "plugins", "installs.json");
177-const index = readJson(indexPath);
178-const configPath = path.join(process.env.HOME, ".openclaw", "openclaw.json");
179-const config = fs.existsSync(configPath) ? readJson(configPath) : {};
180-const allowLegacyCompat = process.env.OPENCLAW_PACKAGE_ACCEPTANCE_LEGACY_COMPAT === "1";
181-if (!allowLegacyCompat && !index.installRecords) {
182-throw new Error("expected modern installRecords in installed plugin index");
183-}
184-const installRecords = allowLegacyCompat
185- ? (index.installRecords ?? index.records ?? config.plugins?.installs ?? {})
186- : (index.installRecords ?? {});
190+const installRecords = getInstallRecords();
187191for (const id of ["marketplace-shortcut", "marketplace-direct"]) {
188192const record = installRecords[id];
189193if (!record) {
@@ -205,6 +209,56 @@ function assertMarketplaceRecords() {
205209}
206210}
207211212+function assertGitPlugin() {
213+const repoUrl = process.argv[3];
214+const gitRef = process.argv[4];
215+assertSimplePlugin(
216+"/tmp/plugins-git.json",
217+"/tmp/plugins-git-inspect.json",
218+"demo-plugin-git",
219+"demo.git",
220+);
221+222+const inspect = readJson("/tmp/plugins-git-inspect.json");
223+if (!Array.isArray(inspect.cliCommands) || !inspect.cliCommands.includes("demo-git")) {
224+throw new Error(`expected demo-git cli command, got ${inspect.cliCommands?.join(", ")}`);
225+}
226+227+const cliOutput = fs.readFileSync("/tmp/plugins-git-cli.txt", "utf8");
228+if (!cliOutput.includes("demo-plugin-git:pong")) {
229+throw new Error(`unexpected git plugin cli output: ${cliOutput.trim()}`);
230+}
231+232+const record = getInstallRecords()["demo-plugin-git"];
233+if (!record) {
234+throw new Error("missing git install record for demo-plugin-git");
235+}
236+if (record.source !== "git") {
237+throw new Error(`unexpected git install source: ${record.source}`);
238+}
239+if (record.gitUrl !== repoUrl) {
240+throw new Error(`unexpected git url: ${record.gitUrl}, expected ${repoUrl}`);
241+}
242+if (record.gitRef !== gitRef) {
243+throw new Error(`unexpected git ref: ${record.gitRef}, expected ${gitRef}`);
244+}
245+if (record.gitCommit !== gitRef) {
246+throw new Error(`unexpected git commit: ${record.gitCommit}, expected ${gitRef}`);
247+}
248+if (record.spec !== `git:${repoUrl}@${gitRef}`) {
249+throw new Error(`unexpected git spec: ${record.spec}`);
250+}
251+252+const installPath = record.installPath?.replace(/^~(?=$|\/)/u, process.env.HOME);
253+if (!installPath || !fs.existsSync(installPath)) {
254+throw new Error(`git install path missing on disk: ${installPath}`);
255+}
256+const extensionsRoot = path.join(process.env.HOME, ".openclaw", "extensions");
257+if (!installPath.startsWith(`${extensionsRoot}${path.sep}`)) {
258+throw new Error(`git install path is outside managed extensions root: ${installPath}`);
259+}
260+}
261+208262function assertRealPathInside(parentPath, childPath, label) {
209263const parentRealPath = fs.realpathSync(parentPath);
210264const childRealPath = fs.realpathSync(childPath);
@@ -414,6 +468,7 @@ const commands = {
414468"bundle-disabled": assertClaudeBundleDisabled,
415469"bundle-inspect": assertClaudeBundleInspect,
416470"slash-install": assertSlashInstall,
471+"plugin-git": assertGitPlugin,
417472"marketplace-list": assertMarketplaceList,
418473"marketplace-installed": assertMarketplaceInstalled,
419474"marketplace-records": assertMarketplaceRecords,
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。