




























@@ -1,7 +1,15 @@
11#!/usr/bin/env -S node --import tsx
2233import { execFileSync, execSync } from "node:child_process";
4-import { existsSync, mkdtempSync, mkdirSync, readdirSync, readFileSync, rmSync } from "node:fs";
4+import {
5+existsSync,
6+mkdtempSync,
7+mkdirSync,
8+readdirSync,
9+readFileSync,
10+rmSync,
11+writeFileSync,
12+} from "node:fs";
513import { tmpdir } from "node:os";
614import { join, resolve } from "node:path";
715import { pathToFileURL } from "node:url";
@@ -211,7 +219,6 @@ export function createPackedBundledPluginPostinstallEnv(
211219return {
212220 ...env,
213221OPENCLAW_DISABLE_BUNDLED_ENTRY_SOURCE_FALLBACK: "1",
214-OPENCLAW_EAGER_BUNDLED_PLUGIN_DEPS: "1",
215222};
216223}
217224@@ -238,20 +245,143 @@ export function collectInstalledBundledPluginRuntimeDepErrors(packageRoot: strin
238245.toSorted((left, right) => left.localeCompare(right));
239246}
240247241-function assertInstalledBundledPluginRuntimeDepsResolved(packageRoot: string): void {
242-const errors = collectInstalledBundledPluginRuntimeDepErrors(packageRoot);
243-if (errors.length === 0) {
244-return;
248+function bundledRuntimeDependencySentinelPath(
249+packageRoot: string,
250+pluginId: string,
251+dependencyName: string,
252+): string {
253+return join(
254+packageRoot,
255+"dist",
256+"extensions",
257+pluginId,
258+"node_modules",
259+ ...dependencyName.split("/"),
260+"package.json",
261+);
262+}
263+264+function bundledRuntimeDependencySentinelCandidates(
265+packageRoot: string,
266+pluginId: string,
267+dependencyName: string,
268+): string[] {
269+const dependencyParts = dependencyName.split("/");
270+return [
271+bundledRuntimeDependencySentinelPath(packageRoot, pluginId, dependencyName),
272+join(packageRoot, "dist", "extensions", "node_modules", ...dependencyParts, "package.json"),
273+join(packageRoot, "node_modules", ...dependencyParts, "package.json"),
274+];
275+}
276+277+function assertBundledRuntimeDependencyAbsent(params: {
278+packageRoot: string;
279+pluginId: string;
280+dependencyName: string;
281+}): void {
282+const sentinelPath = bundledRuntimeDependencySentinelCandidates(
283+params.packageRoot,
284+params.pluginId,
285+params.dependencyName,
286+).find((candidate) => existsSync(candidate));
287+if (sentinelPath) {
288+throw new Error(
289+`release-check: ${params.pluginId} runtime dependency ${params.dependencyName} was installed before plugin activation (${sentinelPath}).`,
290+);
245291}
246-console.error("release-check: packed install is missing bundled plugin runtime dependencies:");
247-for (const error of errors) {
248-console.error(` - ${error}`);
292+}
293+294+function assertBundledRuntimeDependencyPresent(params: {
295+packageRoot: string;
296+pluginId: string;
297+dependencyName: string;
298+}): void {
299+const sentinelPath = bundledRuntimeDependencySentinelCandidates(
300+params.packageRoot,
301+params.pluginId,
302+params.dependencyName,
303+).find((candidate) => existsSync(candidate));
304+if (sentinelPath) {
305+return;
249306}
250307throw new Error(
251-"release-check: bundled plugin runtime dependencies were not installed after packed postinstall.",
308+`release-check: ${params.pluginId} runtime dependency ${params.dependencyName} was not installed during plugin activation.`,
252309);
253310}
254311312+function writePackedBundledPluginActivationConfig(homeDir: string): void {
313+const configPath = join(homeDir, ".openclaw", "openclaw.json");
314+mkdirSync(join(homeDir, ".openclaw"), { recursive: true });
315+writeFileSync(
316+configPath,
317+`${JSON.stringify(
318+ {
319+ agents: {
320+ defaults: {
321+ model: { primary: "openai/gpt-4.1-mini" },
322+ },
323+ },
324+ channels: {
325+ feishu: {
326+ enabled: true,
327+ },
328+ },
329+ models: {
330+ providers: {
331+ openai: {
332+ apiKey: "sk-openclaw-release-check",
333+ baseUrl: "https://api.openai.com/v1",
334+ models: [],
335+ },
336+ },
337+ },
338+ plugins: {
339+ enabled: true,
340+ entries: {
341+ feishu: {
342+ enabled: true,
343+ },
344+ },
345+ },
346+ },
347+ null,
348+ 2,
349+ )}\n`,
350+"utf8",
351+);
352+}
353+354+function runPackedBundledPluginActivationSmoke(packageRoot: string, tmpRoot: string): void {
355+const lazyDeps = [
356+{ pluginId: "browser", dependencyName: "playwright-core" },
357+{ pluginId: "feishu", dependencyName: "@larksuiteoapi/node-sdk" },
358+] as const;
359+360+for (const dep of lazyDeps) {
361+assertBundledRuntimeDependencyAbsent({ packageRoot, ...dep });
362+}
363+364+const homeDir = join(tmpRoot, "activation-home");
365+mkdirSync(homeDir, { recursive: true });
366+writePackedBundledPluginActivationConfig(homeDir);
367+execFileSync(process.execPath, [join(packageRoot, "openclaw.mjs"), "plugins", "doctor"], {
368+cwd: packageRoot,
369+stdio: "inherit",
370+env: {
371+ ...process.env,
372+HOME: homeDir,
373+OPENAI_API_KEY: "sk-openclaw-release-check",
374+OPENCLAW_DISABLE_BUNDLED_ENTRY_SOURCE_FALLBACK: "1",
375+OPENCLAW_NO_ONBOARD: "1",
376+OPENCLAW_SUPPRESS_NOTES: "1",
377+},
378+});
379+380+for (const dep of lazyDeps) {
381+assertBundledRuntimeDependencyPresent({ packageRoot, ...dep });
382+}
383+}
384+255385function runPackedBundledChannelEntrySmoke(): void {
256386const tmpRoot = mkdtempSync(join(tmpdir(), "openclaw-release-pack-smoke-"));
257387try {
@@ -265,7 +395,7 @@ function runPackedBundledChannelEntrySmoke(): void {
265395266396const packageRoot = join(resolveGlobalRoot(prefixDir, tmpRoot), "openclaw");
267397runPackedBundledPluginPostinstall(packageRoot);
268-assertInstalledBundledPluginRuntimeDepsResolved(packageRoot);
398+runPackedBundledPluginActivationSmoke(packageRoot, tmpRoot);
269399execFileSync(
270400process.execPath,
271401[
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。