Vendor OpenClaw source as Adolf fork baseline
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Some checks failed
ClawSweeper Dispatch / dispatch (push) Has been cancelled
CodeQL / Security High (actions) (push) Has been cancelled
CodeQL / Security High (channel-runtime-boundary) (push) Has been cancelled
CodeQL / Security High (core-auth-secrets) (push) Has been cancelled
CodeQL / Security High (mcp-process-tool-boundary) (push) Has been cancelled
CodeQL / Security High (network-ssrf-boundary) (push) Has been cancelled
CodeQL / Security High (plugin-trust-boundary) (push) Has been cancelled
CodeQL / Security High (process-exec-boundary) (push) Has been cancelled
Docs Sync Publish Repo / sync-publish-repo (push) Has been cancelled
Docs / docs (push) Has been cancelled
OpenClaw Stable Main Closeout / Resolve stable release closeout inputs (push) Has been cancelled
OpenClaw Stable Main Closeout / Verify stable main closeout (push) Has been cancelled
Workflow Sanity / no-tabs (push) Has been cancelled
Workflow Sanity / actionlint (push) Has been cancelled
Workflow Sanity / generated-doc-baselines (push) Has been cancelled
CI / runner-admission (push) Has been cancelled
CI / preflight (push) Has been cancelled
CI / security-fast (push) Has been cancelled
CI / pnpm-store-warmup (push) Has been cancelled
CI / build-artifacts (push) Has been cancelled
CI / native-i18n (push) Has been cancelled
CI / ${{ matrix.check_name }} (push) Has been cancelled
CI / ${{ matrix.checkName }} (push) Has been cancelled
CI / checks-node-compat-node22 (push) Has been cancelled
CI / check-bundled-channel-config-metadata (push) Has been cancelled
CI / check-dependencies (push) Has been cancelled
CI / check-guards (push) Has been cancelled
CI / check-lint (push) Has been cancelled
CI / check-prod-types (push) Has been cancelled
CI / check-shrinkwrap (push) Has been cancelled
CI / check-test-types (push) Has been cancelled
CI / check-additional-boundaries-a (push) Has been cancelled
CI / check-additional-boundaries-bcd (push) Has been cancelled
CI / check-additional-extension-bundled (push) Has been cancelled
CI / check-additional-extension-channels (push) Has been cancelled
CI / check-additional-extension-package-boundary (push) Has been cancelled
CI / check-additional-runtime-topology-architecture (push) Has been cancelled
CI / check-session-accessor-boundary (push) Has been cancelled
CI / check-session-transcript-reader-boundary (push) Has been cancelled
CI / check-docs (push) Has been cancelled
CI / skills-python (push) Has been cancelled
CI / macos-swift (push) Has been cancelled
CI / ios-build (push) Has been cancelled
CI / ci-timings-summary (push) Has been cancelled
Native App Locale Refresh / Refresh native fa (push) Has been cancelled
Native App Locale Refresh / Refresh native fr (push) Has been cancelled
Native App Locale Refresh / Refresh native hi (push) Has been cancelled
Native App Locale Refresh / Refresh native id (push) Has been cancelled
Native App Locale Refresh / Refresh native it (push) Has been cancelled
Native App Locale Refresh / Refresh native ja-JP (push) Has been cancelled
Control UI Locale Refresh / plan (push) Has been cancelled
Control UI Locale Refresh / Refresh ${{ matrix.locale }} (push) Has been cancelled
Control UI Locale Refresh / Commit control UI locale refresh (push) Has been cancelled
Live Media Runner Image / Build live media runner image (push) Has been cancelled
Native App Locale Refresh / Refresh native ar (push) Has been cancelled
Native App Locale Refresh / Refresh native de (push) Has been cancelled
Native App Locale Refresh / Refresh native es (push) Has been cancelled
Native App Locale Refresh / Refresh native ko (push) Has been cancelled
Native App Locale Refresh / Refresh native nl (push) Has been cancelled
Native App Locale Refresh / Refresh native pl (push) Has been cancelled
Native App Locale Refresh / Refresh native pt-BR (push) Has been cancelled
Native App Locale Refresh / Refresh native ru (push) Has been cancelled
Native App Locale Refresh / Refresh native sv (push) Has been cancelled
Native App Locale Refresh / Refresh native th (push) Has been cancelled
Native App Locale Refresh / Refresh native tr (push) Has been cancelled
Native App Locale Refresh / Refresh native uk (push) Has been cancelled
Native App Locale Refresh / Refresh native vi (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-CN (push) Has been cancelled
Native App Locale Refresh / Refresh native zh-TW (push) Has been cancelled
Native App Locale Refresh / Commit native locale refresh (push) Has been cancelled
Plugin Init Scaffold Validation / Validate provider scaffold (push) Has been cancelled
Plugin NPM Release / preview_plugins_npm (push) Has been cancelled
Plugin NPM Release / Validate release publish approval (push) Has been cancelled
Plugin NPM Release / preview_plugin_pack (push) Has been cancelled
Plugin NPM Release / publish_plugins_npm (push) Has been cancelled
Sandbox Common Smoke / sandbox-common-smoke (push) Has been cancelled
Website Installer Sync / static (push) Has been cancelled
Website Installer Sync / linux-docker (push) Has been cancelled
Website Installer Sync / macos-installer (push) Has been cancelled
Website Installer Sync / windows-installer (push) Has been cancelled
Website Installer Sync / sync-website (push) Has been cancelled
Adolf is a fork/vendored clone of github.com/openclaw/openclaw (v2026.6.11), free to diverge. Tree copied sans upstream .git; upstream remote added for future syncs. Node pinned to 24 (.nvmrc); engines already require >=22.19. Preserves docs/ARCHITECTURE.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeqyaxJF2nbRXJtae2kNB2
This commit is contained in:
224
scripts/e2e/lib/release-scenarios/assertions.mjs
Normal file
224
scripts/e2e/lib/release-scenarios/assertions.mjs
Normal file
@@ -0,0 +1,224 @@
|
||||
// Assertions for release scenario E2E packages and plugin state.
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
import { DatabaseSync } from "node:sqlite";
|
||||
import {
|
||||
assertAgentReplyContainsMarker,
|
||||
assertOpenAiRequestLogUsed,
|
||||
} from "../agent-turn-output.mjs";
|
||||
import { assertOpenAiEnvAuthProfileStore } from "../auth-profile-store-assertions.mjs";
|
||||
import {
|
||||
applyMockOpenAiModelConfig,
|
||||
parseMockOpenAiPort,
|
||||
} from "../fixtures/mock-openai-config.mjs";
|
||||
import { readPluginInstallRecords } from "../plugin-index-sqlite.mjs";
|
||||
import {
|
||||
ERROR_DETAIL_TAIL_BYTES,
|
||||
fileContainsText,
|
||||
readJson,
|
||||
} from "../release-assertion-files.mjs";
|
||||
import { readTextFileTail } from "../text-file-utils.mjs";
|
||||
|
||||
const command = process.argv[2];
|
||||
|
||||
function assert(condition, message) {
|
||||
if (!condition) {
|
||||
throw new Error(message);
|
||||
}
|
||||
}
|
||||
|
||||
function configPath() {
|
||||
return (
|
||||
process.env.OPENCLAW_CONFIG_PATH ??
|
||||
path.join(process.env.HOME ?? "", ".openclaw", "openclaw.json")
|
||||
);
|
||||
}
|
||||
|
||||
function writeConfig(cfg) {
|
||||
fs.writeFileSync(configPath(), `${JSON.stringify(cfg, null, 2)}\n`);
|
||||
}
|
||||
|
||||
function authProfilesPath() {
|
||||
return path.join(
|
||||
process.env.HOME ?? "",
|
||||
".openclaw",
|
||||
"agents",
|
||||
"main",
|
||||
"agent",
|
||||
"auth-profiles.json",
|
||||
);
|
||||
}
|
||||
|
||||
function authProfilesDatabasePath() {
|
||||
return path.join(
|
||||
process.env.HOME ?? "",
|
||||
".openclaw",
|
||||
"agents",
|
||||
"main",
|
||||
"agent",
|
||||
"openclaw-agent.sqlite",
|
||||
);
|
||||
}
|
||||
|
||||
function readAuthProfileStoreSqliteText() {
|
||||
const dbPath = authProfilesDatabasePath();
|
||||
if (!fs.existsSync(dbPath)) {
|
||||
return "";
|
||||
}
|
||||
let db;
|
||||
try {
|
||||
db = new DatabaseSync(dbPath, { readOnly: true });
|
||||
const row = db
|
||||
.prepare("SELECT store_json FROM auth_profile_store WHERE store_key = ?")
|
||||
.get("primary");
|
||||
return typeof row?.store_json === "string" ? row.store_json : "";
|
||||
} catch {
|
||||
return "";
|
||||
} finally {
|
||||
db?.close();
|
||||
}
|
||||
}
|
||||
|
||||
function readStateText() {
|
||||
const paths = [configPath(), authProfilesPath()].filter((file) => fs.existsSync(file));
|
||||
return [...paths.map((file) => fs.readFileSync(file, "utf8")), readAuthProfileStoreSqliteText()]
|
||||
.filter(Boolean)
|
||||
.join("\n");
|
||||
}
|
||||
|
||||
function configureMockOpenAi() {
|
||||
const mockPort = parseMockOpenAiPort(process.argv[3]);
|
||||
const cfg = readJson(configPath());
|
||||
applyMockOpenAiModelConfig(cfg, { mockPort, includeImageDefaults: true });
|
||||
writeConfig(cfg);
|
||||
}
|
||||
|
||||
function assertOpenAiEnvRef() {
|
||||
const rawKey = process.argv[3];
|
||||
assert(fs.existsSync(configPath()), "openclaw.json missing");
|
||||
assertOpenAiEnvAuthProfileStore(readAuthProfileStoreSqliteText(), {
|
||||
missingMessage: "OpenAI env ref was not persisted",
|
||||
envRefMessage: "OpenAI env ref was not persisted",
|
||||
rawKeyMessage: "raw OpenAI key was persisted",
|
||||
rawKeyNeedle: rawKey,
|
||||
});
|
||||
assert(!readStateText().includes(rawKey), "raw OpenAI key was persisted");
|
||||
}
|
||||
|
||||
function assertSessionMemoryHookEnabled() {
|
||||
const cfg = readJson(configPath());
|
||||
assert(
|
||||
cfg.hooks?.internal?.entries?.["session-memory"]?.enabled === true,
|
||||
"session-memory hook was not enabled",
|
||||
);
|
||||
}
|
||||
|
||||
function assertAgentTurn() {
|
||||
const marker = process.argv[3];
|
||||
const outputPath = process.argv[4];
|
||||
const requestLogPath = process.argv[5];
|
||||
assertAgentReplyContainsMarker(marker, outputPath);
|
||||
assertOpenAiRequestLogUsed(requestLogPath, "mock OpenAI");
|
||||
}
|
||||
|
||||
function assertFileContains() {
|
||||
const file = process.argv[3];
|
||||
const needle = process.argv[4];
|
||||
assert(
|
||||
fileContainsText(file, needle),
|
||||
`${file} did not contain ${needle}. Output tail: ${readTextFileTail(file, ERROR_DETAIL_TAIL_BYTES)}`,
|
||||
);
|
||||
}
|
||||
|
||||
function assertPackageVersion() {
|
||||
const packageRoot = process.argv[3];
|
||||
const expectedVersion = process.argv[4];
|
||||
const label = process.argv[5] ?? "package";
|
||||
assert(packageRoot, "missing package root");
|
||||
assert(expectedVersion, "missing expected package version");
|
||||
const packageJsonPath = path.join(packageRoot, "package.json");
|
||||
const packageJson = readJson(packageJsonPath);
|
||||
assert(
|
||||
packageJson.version === expectedVersion,
|
||||
`${label} package version mismatch: expected ${expectedVersion}, got ${packageJson.version}`,
|
||||
);
|
||||
}
|
||||
|
||||
function assertImageDescribe() {
|
||||
const outputPath = process.argv[3];
|
||||
const requestLogPath = process.argv[4];
|
||||
const payload = readJson(outputPath);
|
||||
assert(payload.ok === true, `image describe failed: ${JSON.stringify(payload)}`);
|
||||
assert(payload.capability === "image.describe", "wrong image describe capability");
|
||||
const output = payload.outputs?.[0];
|
||||
assert(output?.text?.includes("OPENCLAW_E2E_OK"), "image description marker missing");
|
||||
assert(output.provider === "openai", `unexpected image provider: ${output?.provider}`);
|
||||
assert(
|
||||
fileContainsText(requestLogPath, "/v1/responses"),
|
||||
"image describe did not hit Responses API",
|
||||
);
|
||||
}
|
||||
|
||||
function assertImageGenerate() {
|
||||
const outputPath = process.argv[3];
|
||||
const requestLogPath = process.argv[4];
|
||||
const payload = readJson(outputPath);
|
||||
assert(payload.ok === true, `image generation failed: ${JSON.stringify(payload)}`);
|
||||
assert(payload.capability === "image.generate", "wrong image generation capability");
|
||||
const output = payload.outputs?.[0];
|
||||
assert(output?.path && fs.existsSync(output.path), `generated image missing: ${output?.path}`);
|
||||
assert(output.mimeType === "image/png", `unexpected generated mime type: ${output.mimeType}`);
|
||||
assert(payload.provider === "openai", `unexpected generation provider: ${payload.provider}`);
|
||||
assert(
|
||||
fileContainsText(requestLogPath, "/v1/images/generations"),
|
||||
"image generation endpoint was not used",
|
||||
);
|
||||
}
|
||||
|
||||
function assertMemorySearch() {
|
||||
const outputPath = process.argv[3];
|
||||
const needle = process.argv[4];
|
||||
const payload = readJson(outputPath);
|
||||
const haystack = JSON.stringify(payload);
|
||||
assert(haystack.includes(needle), `memory search missed ${needle}: ${haystack}`);
|
||||
}
|
||||
|
||||
function assertPluginUninstalled() {
|
||||
const pluginId = process.argv[3];
|
||||
const cliRoot = process.argv[4];
|
||||
const cfg = readJson(configPath());
|
||||
const installRecords = readPluginInstallRecords({ configPath: configPath() });
|
||||
assert(!installRecords[pluginId], `install record still present for ${pluginId}`);
|
||||
assert(!cfg.plugins?.entries?.[pluginId], `plugin config entry still present for ${pluginId}`);
|
||||
const managedRoot = path.join(
|
||||
process.env.HOME ?? "",
|
||||
".openclaw",
|
||||
"plugins",
|
||||
"installed",
|
||||
pluginId,
|
||||
);
|
||||
assert(!fs.existsSync(managedRoot), `managed plugin directory still present: ${managedRoot}`);
|
||||
if (cliRoot) {
|
||||
const list = JSON.stringify(installRecords);
|
||||
assert(!list.includes(cliRoot), `install records still mention CLI root ${cliRoot}`);
|
||||
}
|
||||
}
|
||||
|
||||
const commands = {
|
||||
"configure-mock-openai": configureMockOpenAi,
|
||||
"assert-openai-env-ref": assertOpenAiEnvRef,
|
||||
"assert-session-memory-hook-enabled": assertSessionMemoryHookEnabled,
|
||||
"assert-agent-turn": assertAgentTurn,
|
||||
"assert-file-contains": assertFileContains,
|
||||
"assert-package-version": assertPackageVersion,
|
||||
"assert-image-describe": assertImageDescribe,
|
||||
"assert-image-generate": assertImageGenerate,
|
||||
"assert-memory-search": assertMemorySearch,
|
||||
"assert-plugin-uninstalled": assertPluginUninstalled,
|
||||
};
|
||||
|
||||
const fn = commands[command];
|
||||
if (!fn) {
|
||||
throw new Error(`unknown release scenario assertion command: ${command ?? "<missing>"}`);
|
||||
}
|
||||
await fn();
|
||||
33
scripts/e2e/lib/release-scenarios/write-cli-plugin.mjs
Normal file
33
scripts/e2e/lib/release-scenarios/write-cli-plugin.mjs
Normal file
@@ -0,0 +1,33 @@
|
||||
// Writes a CLI plugin fixture for release scenario E2E tests.
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const [dir, id, version, method, name, cliRoot, cliOutput] = process.argv.slice(2);
|
||||
|
||||
if (!dir || !id || !version || !method || !name || !cliRoot || !cliOutput) {
|
||||
throw new Error(
|
||||
"usage: write-cli-plugin.mjs <dir> <id> <version> <method> <name> <cliRoot> <cliOutput>",
|
||||
);
|
||||
}
|
||||
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(dir, "package.json"),
|
||||
`${JSON.stringify(
|
||||
{
|
||||
name: `@openclaw/${id}`,
|
||||
version,
|
||||
openclaw: { extensions: ["./index.js"] },
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(dir, "index.js"),
|
||||
`module.exports = { id: ${JSON.stringify(id)}, name: ${JSON.stringify(name)}, register(api) { api.registerGatewayMethod(${JSON.stringify(method)}, async () => ({ ok: true, version: ${JSON.stringify(version)} })); api.registerCli(({ program }) => { const root = program.command(${JSON.stringify(cliRoot)}).description(${JSON.stringify(`${name} fixture command`)}); root.command("ping").description("Print fixture ping output").action(() => { console.log(${JSON.stringify(cliOutput)}); }); }, { descriptors: [{ name: ${JSON.stringify(cliRoot)}, description: ${JSON.stringify(`${name} fixture command`)}, hasSubcommands: true }] }); }, };\n`,
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(dir, "openclaw.plugin.json"),
|
||||
`${JSON.stringify({ id, configSchema: { type: "object", properties: {} } }, null, 2)}\n`,
|
||||
);
|
||||
42
scripts/e2e/lib/release-scenarios/write-marketplace.mjs
Normal file
42
scripts/e2e/lib/release-scenarios/write-marketplace.mjs
Normal file
@@ -0,0 +1,42 @@
|
||||
// Writes a marketplace fixture for release scenario E2E tests.
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
const [root, alias, ...plugins] = process.argv.slice(2);
|
||||
|
||||
if (!root || !alias || plugins.length === 0) {
|
||||
throw new Error("usage: write-marketplace.mjs <root> <alias> <pluginId>...");
|
||||
}
|
||||
|
||||
fs.mkdirSync(path.join(root, ".claude-plugin"), { recursive: true });
|
||||
fs.mkdirSync(path.join(process.env.HOME, ".claude", "plugins"), { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(root, ".claude-plugin", "marketplace.json"),
|
||||
`${JSON.stringify(
|
||||
{
|
||||
name: "Release Fixture Marketplace",
|
||||
version: "1.0.0",
|
||||
plugins: plugins.map((pluginId) => ({
|
||||
name: pluginId,
|
||||
version: "0.0.1",
|
||||
description: `${pluginId} release fixture`,
|
||||
source: { type: "path", path: `./plugins/${pluginId}` },
|
||||
})),
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
fs.writeFileSync(
|
||||
path.join(process.env.HOME, ".claude", "plugins", "known_marketplaces.json"),
|
||||
`${JSON.stringify(
|
||||
{
|
||||
[alias]: {
|
||||
installLocation: root,
|
||||
source: { type: "github", repo: "openclaw/release-fixture-marketplace" },
|
||||
},
|
||||
},
|
||||
null,
|
||||
2,
|
||||
)}\n`,
|
||||
);
|
||||
Reference in New Issue
Block a user