mirror of
https://github.com/openclaw/openclaw.git
synced 2026-03-12 07:20:45 +00:00
Plugins: add root-alias shim and cache/docs updates
This commit is contained in:
@@ -13,14 +13,68 @@ function hasMonolithicRootImport(content: string): boolean {
|
||||
return ROOT_IMPORT_PATTERNS.some((pattern) => pattern.test(content));
|
||||
}
|
||||
|
||||
function isSourceFile(filePath: string): boolean {
|
||||
if (filePath.endsWith(".d.ts")) {
|
||||
return false;
|
||||
}
|
||||
return /\.(?:[cm]?ts|[cm]?js|tsx|jsx)$/u.test(filePath);
|
||||
}
|
||||
|
||||
function collectPluginSourceFiles(rootDir: string): string[] {
|
||||
const srcDir = path.join(rootDir, "src");
|
||||
if (!fs.existsSync(srcDir)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const files: string[] = [];
|
||||
const stack: string[] = [srcDir];
|
||||
while (stack.length > 0) {
|
||||
const current = stack.pop();
|
||||
if (!current) {
|
||||
continue;
|
||||
}
|
||||
let entries: fs.Dirent[] = [];
|
||||
try {
|
||||
entries = fs.readdirSync(current, { withFileTypes: true });
|
||||
} catch {
|
||||
continue;
|
||||
}
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(current, entry.name);
|
||||
if (entry.isDirectory()) {
|
||||
if (
|
||||
entry.name === "node_modules" ||
|
||||
entry.name === "dist" ||
|
||||
entry.name === ".git" ||
|
||||
entry.name === "coverage"
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
stack.push(fullPath);
|
||||
continue;
|
||||
}
|
||||
if (entry.isFile() && isSourceFile(fullPath)) {
|
||||
files.push(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
function main() {
|
||||
const discovery = discoverOpenClawPlugins({});
|
||||
const bundledEntryFiles = [
|
||||
...new Set(discovery.candidates.filter((c) => c.origin === "bundled").map((c) => c.source)),
|
||||
];
|
||||
const bundledCandidates = discovery.candidates.filter((c) => c.origin === "bundled");
|
||||
const filesToCheck = new Set<string>();
|
||||
for (const candidate of bundledCandidates) {
|
||||
filesToCheck.add(candidate.source);
|
||||
for (const srcFile of collectPluginSourceFiles(candidate.rootDir)) {
|
||||
filesToCheck.add(srcFile);
|
||||
}
|
||||
}
|
||||
|
||||
const offenders: string[] = [];
|
||||
for (const entryFile of bundledEntryFiles) {
|
||||
for (const entryFile of filesToCheck) {
|
||||
let content = "";
|
||||
try {
|
||||
content = fs.readFileSync(entryFile, "utf8");
|
||||
@@ -33,17 +87,19 @@ function main() {
|
||||
}
|
||||
|
||||
if (offenders.length > 0) {
|
||||
console.error("Bundled plugin entrypoints must not import monolithic openclaw/plugin-sdk.");
|
||||
console.error("Bundled plugin source files must not import monolithic openclaw/plugin-sdk.");
|
||||
for (const file of offenders.toSorted()) {
|
||||
const relative = path.relative(process.cwd(), file) || file;
|
||||
console.error(`- ${relative}`);
|
||||
}
|
||||
console.error("Use openclaw/plugin-sdk/<channel> for channel plugins or /core for others.");
|
||||
console.error(
|
||||
"Use openclaw/plugin-sdk/<channel> for channel plugins, /core for startup surfaces, or /compat for broader internals.",
|
||||
);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log(
|
||||
`OK: bundled entrypoints use scoped plugin-sdk subpaths (${bundledEntryFiles.length} checked).`,
|
||||
`OK: bundled plugin source files use scoped plugin-sdk subpaths (${filesToCheck.size} checked).`,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ const exportSet = new Set(exportedNames);
|
||||
|
||||
const requiredSubpathEntries = [
|
||||
"core",
|
||||
"compat",
|
||||
"telegram",
|
||||
"discord",
|
||||
"slack",
|
||||
@@ -53,6 +54,8 @@ const requiredSubpathEntries = [
|
||||
"account-id",
|
||||
];
|
||||
|
||||
const requiredRuntimeShimEntries = ["root-alias.cjs"];
|
||||
|
||||
// Critical functions that channel extension plugins import from openclaw/plugin-sdk.
|
||||
// If any of these are missing, plugins will fail at runtime with:
|
||||
// TypeError: (0 , _pluginSdk.<name>) is not a function
|
||||
@@ -101,6 +104,14 @@ for (const entry of requiredSubpathEntries) {
|
||||
}
|
||||
}
|
||||
|
||||
for (const entry of requiredRuntimeShimEntries) {
|
||||
const shimPath = resolve(__dirname, "..", "dist", "plugin-sdk", entry);
|
||||
if (!existsSync(shimPath)) {
|
||||
console.error(`MISSING RUNTIME SHIM: dist/plugin-sdk/${entry}`);
|
||||
missing += 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (missing > 0) {
|
||||
console.error(
|
||||
`\nERROR: ${missing} required plugin-sdk artifact(s) missing (named exports or subpath files).`,
|
||||
|
||||
10
scripts/copy-plugin-sdk-root-alias.mjs
Normal file
10
scripts/copy-plugin-sdk-root-alias.mjs
Normal file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { copyFileSync, mkdirSync } from "node:fs";
|
||||
import { dirname, resolve } from "node:path";
|
||||
|
||||
const source = resolve("src/plugin-sdk/root-alias.cjs");
|
||||
const target = resolve("dist/plugin-sdk/root-alias.cjs");
|
||||
|
||||
mkdirSync(dirname(target), { recursive: true });
|
||||
copyFileSync(source, target);
|
||||
@@ -16,6 +16,9 @@ const requiredPathGroups = [
|
||||
"dist/plugin-sdk/index.d.ts",
|
||||
"dist/plugin-sdk/core.js",
|
||||
"dist/plugin-sdk/core.d.ts",
|
||||
"dist/plugin-sdk/root-alias.cjs",
|
||||
"dist/plugin-sdk/compat.js",
|
||||
"dist/plugin-sdk/compat.d.ts",
|
||||
"dist/plugin-sdk/telegram.js",
|
||||
"dist/plugin-sdk/telegram.d.ts",
|
||||
"dist/plugin-sdk/discord.js",
|
||||
|
||||
@@ -9,6 +9,7 @@ import path from "node:path";
|
||||
const entrypoints = [
|
||||
"index",
|
||||
"core",
|
||||
"compat",
|
||||
"telegram",
|
||||
"discord",
|
||||
"slack",
|
||||
|
||||
Reference in New Issue
Block a user