mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 12:37:27 +00:00
refactor: rename to openclaw
This commit is contained in:
@@ -3,7 +3,7 @@ import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
|
||||
export function resolveBundledPluginsDir(): string | undefined {
|
||||
const override = process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR?.trim();
|
||||
const override = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR?.trim();
|
||||
if (override) return override;
|
||||
|
||||
// bun --compile: ship a sibling `extensions/` next to the executable.
|
||||
|
||||
@@ -7,7 +7,7 @@ const mocks = vi.hoisted(() => ({
|
||||
}));
|
||||
|
||||
vi.mock("./loader.js", () => ({
|
||||
loadMoltbotPlugins: () => ({
|
||||
loadOpenClawPlugins: () => ({
|
||||
cliRegistrars: [
|
||||
{
|
||||
pluginId: "memory-core",
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import type { Command } from "commander";
|
||||
|
||||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { loadConfig } from "../config/config.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { loadMoltbotPlugins } from "./loader.js";
|
||||
import { loadOpenClawPlugins } from "./loader.js";
|
||||
import type { PluginLogger } from "./types.js";
|
||||
|
||||
const log = createSubsystemLogger("plugins");
|
||||
|
||||
export function registerPluginCliCommands(program: Command, cfg?: MoltbotConfig) {
|
||||
export function registerPluginCliCommands(program: Command, cfg?: OpenClawConfig) {
|
||||
const config = cfg ?? loadConfig();
|
||||
const workspaceDir = resolveAgentWorkspaceDir(config, resolveDefaultAgentId(config));
|
||||
const logger: PluginLogger = {
|
||||
@@ -18,7 +18,7 @@ export function registerPluginCliCommands(program: Command, cfg?: MoltbotConfig)
|
||||
error: (msg: string) => log.error(msg),
|
||||
debug: (msg: string) => log.debug(msg),
|
||||
};
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
config,
|
||||
workspaceDir,
|
||||
logger,
|
||||
|
||||
@@ -5,15 +5,15 @@
|
||||
* These commands are processed before built-in commands and before agent invocation.
|
||||
*/
|
||||
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type {
|
||||
MoltbotPluginCommandDefinition,
|
||||
OpenClawPluginCommandDefinition,
|
||||
PluginCommandContext,
|
||||
PluginCommandResult,
|
||||
} from "./types.js";
|
||||
import { logVerbose } from "../globals.js";
|
||||
|
||||
type RegisteredPluginCommand = MoltbotPluginCommandDefinition & {
|
||||
type RegisteredPluginCommand = OpenClawPluginCommandDefinition & {
|
||||
pluginId: string;
|
||||
};
|
||||
|
||||
@@ -104,7 +104,7 @@ export type CommandRegistrationResult = {
|
||||
*/
|
||||
export function registerPluginCommand(
|
||||
pluginId: string,
|
||||
command: MoltbotPluginCommandDefinition,
|
||||
command: OpenClawPluginCommandDefinition,
|
||||
): CommandRegistrationResult {
|
||||
// Prevent registration while commands are being processed
|
||||
if (registryLocked) {
|
||||
@@ -221,7 +221,7 @@ export async function executePluginCommand(params: {
|
||||
channel: string;
|
||||
isAuthorizedSender: boolean;
|
||||
commandBody: string;
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
}): Promise<PluginCommandResult> {
|
||||
const { command, args, senderId, channel, isAuthorizedSender, commandBody, config } = params;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { MoltbotPluginConfigSchema } from "./types.js";
|
||||
import type { OpenClawPluginConfigSchema } from "./types.js";
|
||||
|
||||
type Issue = { path: Array<string | number>; message: string };
|
||||
|
||||
@@ -10,7 +10,7 @@ function error(message: string): SafeParseResult {
|
||||
return { success: false, error: { issues: [{ path: [], message }] } };
|
||||
}
|
||||
|
||||
export function emptyPluginConfigSchema(): MoltbotPluginConfigSchema {
|
||||
export function emptyPluginConfigSchema(): OpenClawPluginConfigSchema {
|
||||
return {
|
||||
safeParse(value: unknown): SafeParseResult {
|
||||
if (value === undefined) return { success: true, data: undefined };
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { defaultSlotIdForKey } from "./slots.js";
|
||||
import type { PluginRecord } from "./registry.js";
|
||||
|
||||
@@ -49,7 +49,7 @@ const normalizePluginEntries = (entries: unknown): NormalizedPluginsConfig["entr
|
||||
};
|
||||
|
||||
export const normalizePluginsConfig = (
|
||||
config?: MoltbotConfig["plugins"],
|
||||
config?: OpenClawConfig["plugins"],
|
||||
): NormalizedPluginsConfig => {
|
||||
const memorySlot = normalizeSlotValue(config?.slots?.memory);
|
||||
return {
|
||||
|
||||
@@ -7,30 +7,30 @@ import { afterEach, describe, expect, it, vi } from "vitest";
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
function makeTempDir() {
|
||||
const dir = path.join(os.tmpdir(), `moltbot-plugins-${randomUUID()}`);
|
||||
const dir = path.join(os.tmpdir(), `openclaw-plugins-${randomUUID()}`);
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
tempDirs.push(dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
async function withStateDir<T>(stateDir: string, fn: () => Promise<T>) {
|
||||
const prev = process.env.CLAWDBOT_STATE_DIR;
|
||||
const prevBundled = process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR;
|
||||
process.env.CLAWDBOT_STATE_DIR = stateDir;
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
const prev = process.env.OPENCLAW_STATE_DIR;
|
||||
const prevBundled = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
|
||||
process.env.OPENCLAW_STATE_DIR = stateDir;
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
vi.resetModules();
|
||||
try {
|
||||
return await fn();
|
||||
} finally {
|
||||
if (prev === undefined) {
|
||||
delete process.env.CLAWDBOT_STATE_DIR;
|
||||
delete process.env.OPENCLAW_STATE_DIR;
|
||||
} else {
|
||||
process.env.CLAWDBOT_STATE_DIR = prev;
|
||||
process.env.OPENCLAW_STATE_DIR = prev;
|
||||
}
|
||||
if (prevBundled === undefined) {
|
||||
delete process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR;
|
||||
delete process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
|
||||
} else {
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = prevBundled;
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = prevBundled;
|
||||
}
|
||||
vi.resetModules();
|
||||
}
|
||||
@@ -46,7 +46,7 @@ afterEach(() => {
|
||||
}
|
||||
});
|
||||
|
||||
describe("discoverMoltbotPlugins", () => {
|
||||
describe("discoverOpenClawPlugins", () => {
|
||||
it("discovers global and workspace extensions", async () => {
|
||||
const stateDir = makeTempDir();
|
||||
const workspaceDir = path.join(stateDir, "workspace");
|
||||
@@ -55,13 +55,13 @@ describe("discoverMoltbotPlugins", () => {
|
||||
fs.mkdirSync(globalExt, { recursive: true });
|
||||
fs.writeFileSync(path.join(globalExt, "alpha.ts"), "export default function () {}", "utf-8");
|
||||
|
||||
const workspaceExt = path.join(workspaceDir, ".clawdbot", "extensions");
|
||||
const workspaceExt = path.join(workspaceDir, ".openclaw", "extensions");
|
||||
fs.mkdirSync(workspaceExt, { recursive: true });
|
||||
fs.writeFileSync(path.join(workspaceExt, "beta.ts"), "export default function () {}", "utf-8");
|
||||
|
||||
const { candidates } = await withStateDir(stateDir, async () => {
|
||||
const { discoverMoltbotPlugins } = await import("./discovery.js");
|
||||
return discoverMoltbotPlugins({ workspaceDir });
|
||||
const { discoverOpenClawPlugins } = await import("./discovery.js");
|
||||
return discoverOpenClawPlugins({ workspaceDir });
|
||||
});
|
||||
|
||||
const ids = candidates.map((c) => c.idHint);
|
||||
@@ -78,7 +78,7 @@ describe("discoverMoltbotPlugins", () => {
|
||||
path.join(globalExt, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "pack",
|
||||
moltbot: { extensions: ["./src/one.ts", "./src/two.ts"] },
|
||||
openclaw: { extensions: ["./src/one.ts", "./src/two.ts"] },
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
@@ -94,8 +94,8 @@ describe("discoverMoltbotPlugins", () => {
|
||||
);
|
||||
|
||||
const { candidates } = await withStateDir(stateDir, async () => {
|
||||
const { discoverMoltbotPlugins } = await import("./discovery.js");
|
||||
return discoverMoltbotPlugins({});
|
||||
const { discoverOpenClawPlugins } = await import("./discovery.js");
|
||||
return discoverOpenClawPlugins({});
|
||||
});
|
||||
|
||||
const ids = candidates.map((c) => c.idHint);
|
||||
@@ -111,8 +111,8 @@ describe("discoverMoltbotPlugins", () => {
|
||||
fs.writeFileSync(
|
||||
path.join(globalExt, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@moltbot/voice-call",
|
||||
moltbot: { extensions: ["./src/index.ts"] },
|
||||
name: "@openclaw/voice-call",
|
||||
openclaw: { extensions: ["./src/index.ts"] },
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
@@ -123,8 +123,8 @@ describe("discoverMoltbotPlugins", () => {
|
||||
);
|
||||
|
||||
const { candidates } = await withStateDir(stateDir, async () => {
|
||||
const { discoverMoltbotPlugins } = await import("./discovery.js");
|
||||
return discoverMoltbotPlugins({});
|
||||
const { discoverOpenClawPlugins } = await import("./discovery.js");
|
||||
return discoverOpenClawPlugins({});
|
||||
});
|
||||
|
||||
const ids = candidates.map((c) => c.idHint);
|
||||
@@ -139,16 +139,16 @@ describe("discoverMoltbotPlugins", () => {
|
||||
fs.writeFileSync(
|
||||
path.join(packDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@moltbot/demo-plugin-dir",
|
||||
moltbot: { extensions: ["./index.js"] },
|
||||
name: "@openclaw/demo-plugin-dir",
|
||||
openclaw: { extensions: ["./index.js"] },
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
fs.writeFileSync(path.join(packDir, "index.js"), "module.exports = {}", "utf-8");
|
||||
|
||||
const { candidates } = await withStateDir(stateDir, async () => {
|
||||
const { discoverMoltbotPlugins } = await import("./discovery.js");
|
||||
return discoverMoltbotPlugins({ extraPaths: [packDir] });
|
||||
const { discoverOpenClawPlugins } = await import("./discovery.js");
|
||||
return discoverOpenClawPlugins({ extraPaths: [packDir] });
|
||||
});
|
||||
|
||||
const ids = candidates.map((c) => c.idHint);
|
||||
|
||||
@@ -5,7 +5,7 @@ import { resolveConfigDir, resolveUserPath } from "../utils.js";
|
||||
import { resolveBundledPluginsDir } from "./bundled-dir.js";
|
||||
import {
|
||||
getPackageManifestMetadata,
|
||||
type MoltbotPackageManifest,
|
||||
type OpenClawPackageManifest,
|
||||
type PackageManifest,
|
||||
} from "./manifest.js";
|
||||
import type { PluginDiagnostic, PluginOrigin } from "./types.js";
|
||||
@@ -22,7 +22,7 @@ export type PluginCandidate = {
|
||||
packageVersion?: string;
|
||||
packageDescription?: string;
|
||||
packageDir?: string;
|
||||
packageMoltbot?: MoltbotPackageManifest;
|
||||
packageManifest?: OpenClawPackageManifest;
|
||||
};
|
||||
|
||||
export type PluginDiscoveryResult = {
|
||||
@@ -63,7 +63,7 @@ function deriveIdHint(params: {
|
||||
if (!rawPackageName) return base;
|
||||
|
||||
// Prefer the unscoped name so config keys stay stable even when the npm
|
||||
// package is scoped (example: @moltbot/voice-call -> voice-call).
|
||||
// package is scoped (example: @openclaw/voice-call -> voice-call).
|
||||
const unscoped = rawPackageName.includes("/")
|
||||
? (rawPackageName.split("/").pop() ?? rawPackageName)
|
||||
: rawPackageName;
|
||||
@@ -97,7 +97,7 @@ function addCandidate(params: {
|
||||
packageVersion: manifest?.version?.trim() || undefined,
|
||||
packageDescription: manifest?.description?.trim() || undefined,
|
||||
packageDir: params.packageDir,
|
||||
packageMoltbot: getPackageManifestMetadata(manifest ?? undefined),
|
||||
packageManifest: getPackageManifestMetadata(manifest ?? undefined),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@ function discoverFromPath(params: {
|
||||
}
|
||||
}
|
||||
|
||||
export function discoverMoltbotPlugins(params: {
|
||||
export function discoverOpenClawPlugins(params: {
|
||||
workspaceDir?: string;
|
||||
extraPaths?: string[];
|
||||
}): PluginDiscoveryResult {
|
||||
@@ -306,15 +306,17 @@ export function discoverMoltbotPlugins(params: {
|
||||
}
|
||||
if (workspaceDir) {
|
||||
const workspaceRoot = resolveUserPath(workspaceDir);
|
||||
const workspaceExt = path.join(workspaceRoot, ".clawdbot", "extensions");
|
||||
discoverInDirectory({
|
||||
dir: workspaceExt,
|
||||
origin: "workspace",
|
||||
workspaceDir: workspaceRoot,
|
||||
candidates,
|
||||
diagnostics,
|
||||
seen,
|
||||
});
|
||||
const workspaceExtDirs = [path.join(workspaceRoot, ".openclaw", "extensions")];
|
||||
for (const dir of workspaceExtDirs) {
|
||||
discoverInDirectory({
|
||||
dir,
|
||||
origin: "workspace",
|
||||
workspaceDir: workspaceRoot,
|
||||
candidates,
|
||||
diagnostics,
|
||||
seen,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
const globalDir = path.join(resolveConfigDir(), "extensions");
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
|
||||
export type PluginEnableResult = {
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
enabled: boolean;
|
||||
reason?: string;
|
||||
};
|
||||
|
||||
function ensureAllowlisted(cfg: MoltbotConfig, pluginId: string): MoltbotConfig {
|
||||
function ensureAllowlisted(cfg: OpenClawConfig, pluginId: string): OpenClawConfig {
|
||||
const allow = cfg.plugins?.allow;
|
||||
if (!Array.isArray(allow) || allow.includes(pluginId)) return cfg;
|
||||
return {
|
||||
@@ -18,7 +18,7 @@ function ensureAllowlisted(cfg: MoltbotConfig, pluginId: string): MoltbotConfig
|
||||
};
|
||||
}
|
||||
|
||||
export function enablePluginInConfig(cfg: MoltbotConfig, pluginId: string): PluginEnableResult {
|
||||
export function enablePluginInConfig(cfg: OpenClawConfig, pluginId: string): PluginEnableResult {
|
||||
if (cfg.plugins?.enabled === false) {
|
||||
return { config: cfg, enabled: false, reason: "plugins disabled" };
|
||||
}
|
||||
@@ -33,7 +33,7 @@ export function enablePluginInConfig(cfg: MoltbotConfig, pluginId: string): Plug
|
||||
enabled: true,
|
||||
},
|
||||
};
|
||||
let next: MoltbotConfig = {
|
||||
let next: OpenClawConfig = {
|
||||
...cfg,
|
||||
plugins: {
|
||||
...cfg.plugins,
|
||||
|
||||
@@ -9,7 +9,7 @@ import { afterEach, describe, expect, it } from "vitest";
|
||||
const tempDirs: string[] = [];
|
||||
|
||||
function makeTempDir() {
|
||||
const dir = path.join(os.tmpdir(), `moltbot-plugin-install-${randomUUID()}`);
|
||||
const dir = path.join(os.tmpdir(), `openclaw-plugin-install-${randomUUID()}`);
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
tempDirs.push(dir);
|
||||
return dir;
|
||||
@@ -88,7 +88,7 @@ afterEach(() => {
|
||||
});
|
||||
|
||||
describe("installPluginFromArchive", () => {
|
||||
it("installs into ~/.clawdbot/extensions and uses unscoped id", async () => {
|
||||
it("installs into ~/.openclaw/extensions and uses unscoped id", async () => {
|
||||
const stateDir = makeTempDir();
|
||||
const workDir = makeTempDir();
|
||||
const pkgDir = path.join(workDir, "package");
|
||||
@@ -96,9 +96,9 @@ describe("installPluginFromArchive", () => {
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@moltbot/voice-call",
|
||||
name: "@openclaw/voice-call",
|
||||
version: "0.0.1",
|
||||
moltbot: { extensions: ["./dist/index.js"] },
|
||||
openclaw: { extensions: ["./dist/index.js"] },
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
@@ -129,9 +129,9 @@ describe("installPluginFromArchive", () => {
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@moltbot/voice-call",
|
||||
name: "@openclaw/voice-call",
|
||||
version: "0.0.1",
|
||||
moltbot: { extensions: ["./dist/index.js"] },
|
||||
openclaw: { extensions: ["./dist/index.js"] },
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
@@ -163,9 +163,9 @@ describe("installPluginFromArchive", () => {
|
||||
zip.file(
|
||||
"package/package.json",
|
||||
JSON.stringify({
|
||||
name: "@moltbot/zipper",
|
||||
name: "@openclaw/zipper",
|
||||
version: "0.0.1",
|
||||
moltbot: { extensions: ["./dist/index.js"] },
|
||||
openclaw: { extensions: ["./dist/index.js"] },
|
||||
}),
|
||||
);
|
||||
zip.file("package/dist/index.js", "export {};");
|
||||
@@ -192,9 +192,9 @@ describe("installPluginFromArchive", () => {
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@moltbot/voice-call",
|
||||
name: "@openclaw/voice-call",
|
||||
version: "0.0.1",
|
||||
moltbot: { extensions: ["./dist/index.js"] },
|
||||
openclaw: { extensions: ["./dist/index.js"] },
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
@@ -210,9 +210,9 @@ describe("installPluginFromArchive", () => {
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@moltbot/voice-call",
|
||||
name: "@openclaw/voice-call",
|
||||
version: "0.0.2",
|
||||
moltbot: { extensions: ["./dist/index.js"] },
|
||||
openclaw: { extensions: ["./dist/index.js"] },
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
@@ -244,14 +244,14 @@ describe("installPluginFromArchive", () => {
|
||||
expect(manifest.version).toBe("0.0.2");
|
||||
});
|
||||
|
||||
it("rejects packages without moltbot.extensions", async () => {
|
||||
it("rejects packages without openclaw.extensions", async () => {
|
||||
const stateDir = makeTempDir();
|
||||
const workDir = makeTempDir();
|
||||
const pkgDir = path.join(workDir, "package");
|
||||
fs.mkdirSync(pkgDir, { recursive: true });
|
||||
fs.writeFileSync(
|
||||
path.join(pkgDir, "package.json"),
|
||||
JSON.stringify({ name: "@moltbot/nope", version: "0.0.1" }),
|
||||
JSON.stringify({ name: "@openclaw/nope", version: "0.0.1" }),
|
||||
"utf-8",
|
||||
);
|
||||
|
||||
@@ -266,6 +266,6 @@ describe("installPluginFromArchive", () => {
|
||||
const result = await installPluginFromArchive({ archivePath, extensionsDir });
|
||||
expect(result.ok).toBe(false);
|
||||
if (result.ok) return;
|
||||
expect(result.error).toContain("moltbot.extensions");
|
||||
expect(result.error).toContain("openclaw.extensions");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import fs from "node:fs/promises";
|
||||
import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { LEGACY_MANIFEST_KEY } from "../compat/legacy-names.js";
|
||||
import { MANIFEST_KEY } from "../compat/legacy-names.js";
|
||||
import { runCommandWithTimeout } from "../process/exec.js";
|
||||
import { CONFIG_DIR, resolveUserPath } from "../utils.js";
|
||||
import {
|
||||
@@ -21,9 +21,7 @@ type PackageManifest = {
|
||||
name?: string;
|
||||
version?: string;
|
||||
dependencies?: Record<string, string>;
|
||||
moltbot?: { extensions?: string[] };
|
||||
[LEGACY_MANIFEST_KEY]?: { extensions?: string[] };
|
||||
};
|
||||
} & Partial<Record<typeof MANIFEST_KEY, { extensions?: string[] }>>;
|
||||
|
||||
export type InstallPluginResult =
|
||||
| {
|
||||
@@ -54,14 +52,14 @@ function safeFileName(input: string): string {
|
||||
return safeDirName(input);
|
||||
}
|
||||
|
||||
async function ensureMoltbotExtensions(manifest: PackageManifest) {
|
||||
const extensions = manifest.moltbot?.extensions ?? manifest[LEGACY_MANIFEST_KEY]?.extensions;
|
||||
async function ensureOpenClawExtensions(manifest: PackageManifest) {
|
||||
const extensions = manifest[MANIFEST_KEY]?.extensions;
|
||||
if (!Array.isArray(extensions)) {
|
||||
throw new Error("package.json missing moltbot.extensions");
|
||||
throw new Error("package.json missing openclaw.extensions");
|
||||
}
|
||||
const list = extensions.map((e) => (typeof e === "string" ? e.trim() : "")).filter(Boolean);
|
||||
if (list.length === 0) {
|
||||
throw new Error("package.json moltbot.extensions is empty");
|
||||
throw new Error("package.json openclaw.extensions is empty");
|
||||
}
|
||||
return list;
|
||||
}
|
||||
@@ -101,7 +99,7 @@ async function installPluginFromPackageDir(params: {
|
||||
|
||||
let extensions: string[];
|
||||
try {
|
||||
extensions = await ensureMoltbotExtensions(manifest);
|
||||
extensions = await ensureOpenClawExtensions(manifest);
|
||||
} catch (err) {
|
||||
return { ok: false, error: String(err) };
|
||||
}
|
||||
@@ -219,7 +217,7 @@ export async function installPluginFromArchive(params: {
|
||||
return { ok: false, error: `unsupported archive: ${archivePath}` };
|
||||
}
|
||||
|
||||
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-plugin-"));
|
||||
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-plugin-"));
|
||||
const extractDir = path.join(tmpDir, "extract");
|
||||
await fs.mkdir(extractDir, { recursive: true });
|
||||
|
||||
@@ -352,7 +350,7 @@ export async function installPluginFromNpmSpec(params: {
|
||||
const spec = params.spec.trim();
|
||||
if (!spec) return { ok: false, error: "missing npm spec" };
|
||||
|
||||
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "moltbot-npm-pack-"));
|
||||
const tmpDir = await fs.mkdtemp(path.join(os.tmpdir(), "openclaw-npm-pack-"));
|
||||
logger.info?.(`Downloading ${spec}…`);
|
||||
const res = await runCommandWithTimeout(["npm", "pack", spec], {
|
||||
timeoutMs: Math.max(timeoutMs, 300_000),
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { PluginInstallRecord } from "../config/types.plugins.js";
|
||||
|
||||
export type PluginInstallUpdate = PluginInstallRecord & { pluginId: string };
|
||||
|
||||
export function recordPluginInstall(
|
||||
cfg: MoltbotConfig,
|
||||
cfg: OpenClawConfig,
|
||||
update: PluginInstallUpdate,
|
||||
): MoltbotConfig {
|
||||
): OpenClawConfig {
|
||||
const { pluginId, ...record } = update;
|
||||
const installs = {
|
||||
...cfg.plugins?.installs,
|
||||
|
||||
@@ -4,16 +4,16 @@ import os from "node:os";
|
||||
import path from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
|
||||
import { loadMoltbotPlugins } from "./loader.js";
|
||||
import { loadOpenClawPlugins } from "./loader.js";
|
||||
|
||||
type TempPlugin = { dir: string; file: string; id: string };
|
||||
|
||||
const tempDirs: string[] = [];
|
||||
const prevBundledDir = process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR;
|
||||
const prevBundledDir = process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
|
||||
const EMPTY_PLUGIN_SCHEMA = { type: "object", additionalProperties: false, properties: {} };
|
||||
|
||||
function makeTempDir() {
|
||||
const dir = path.join(os.tmpdir(), `moltbot-plugin-${randomUUID()}`);
|
||||
const dir = path.join(os.tmpdir(), `openclaw-plugin-${randomUUID()}`);
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
tempDirs.push(dir);
|
||||
return dir;
|
||||
@@ -30,7 +30,7 @@ function writePlugin(params: {
|
||||
const file = path.join(dir, filename);
|
||||
fs.writeFileSync(file, params.body, "utf-8");
|
||||
fs.writeFileSync(
|
||||
path.join(dir, "moltbot.plugin.json"),
|
||||
path.join(dir, "openclaw.plugin.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
id: params.id,
|
||||
@@ -53,13 +53,13 @@ afterEach(() => {
|
||||
}
|
||||
}
|
||||
if (prevBundledDir === undefined) {
|
||||
delete process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR;
|
||||
delete process.env.OPENCLAW_BUNDLED_PLUGINS_DIR;
|
||||
} else {
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = prevBundledDir;
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = prevBundledDir;
|
||||
}
|
||||
});
|
||||
|
||||
describe("loadMoltbotPlugins", () => {
|
||||
describe("loadOpenClawPlugins", () => {
|
||||
it("disables bundled plugins by default", () => {
|
||||
const bundledDir = makeTempDir();
|
||||
writePlugin({
|
||||
@@ -68,9 +68,9 @@ describe("loadMoltbotPlugins", () => {
|
||||
dir: bundledDir,
|
||||
filename: "bundled.ts",
|
||||
});
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = bundledDir;
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = bundledDir;
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
config: {
|
||||
plugins: {
|
||||
@@ -82,7 +82,7 @@ describe("loadMoltbotPlugins", () => {
|
||||
const bundled = registry.plugins.find((entry) => entry.id === "bundled");
|
||||
expect(bundled?.status).toBe("disabled");
|
||||
|
||||
const enabledRegistry = loadMoltbotPlugins({
|
||||
const enabledRegistry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
config: {
|
||||
plugins: {
|
||||
@@ -125,9 +125,9 @@ describe("loadMoltbotPlugins", () => {
|
||||
dir: bundledDir,
|
||||
filename: "telegram.ts",
|
||||
});
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = bundledDir;
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = bundledDir;
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
config: {
|
||||
plugins: {
|
||||
@@ -152,9 +152,9 @@ describe("loadMoltbotPlugins", () => {
|
||||
dir: bundledDir,
|
||||
filename: "memory-core.ts",
|
||||
});
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = bundledDir;
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = bundledDir;
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
config: {
|
||||
plugins: {
|
||||
@@ -177,10 +177,10 @@ describe("loadMoltbotPlugins", () => {
|
||||
fs.writeFileSync(
|
||||
path.join(pluginDir, "package.json"),
|
||||
JSON.stringify({
|
||||
name: "@moltbot/memory-core",
|
||||
name: "@openclaw/memory-core",
|
||||
version: "1.2.3",
|
||||
description: "Memory plugin package",
|
||||
moltbot: { extensions: ["./index.ts"] },
|
||||
openclaw: { extensions: ["./index.ts"] },
|
||||
}),
|
||||
"utf-8",
|
||||
);
|
||||
@@ -191,9 +191,9 @@ describe("loadMoltbotPlugins", () => {
|
||||
filename: "index.ts",
|
||||
});
|
||||
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = bundledDir;
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = bundledDir;
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
config: {
|
||||
plugins: {
|
||||
@@ -211,13 +211,13 @@ describe("loadMoltbotPlugins", () => {
|
||||
expect(memory?.version).toBe("1.2.3");
|
||||
});
|
||||
it("loads plugins from config paths", () => {
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
const plugin = writePlugin({
|
||||
id: "allowed",
|
||||
body: `export default { id: "allowed", register(api) { api.registerGatewayMethod("allowed.ping", ({ respond }) => respond(true, { ok: true })); } };`,
|
||||
});
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
workspaceDir: plugin.dir,
|
||||
config: {
|
||||
@@ -234,13 +234,13 @@ describe("loadMoltbotPlugins", () => {
|
||||
});
|
||||
|
||||
it("denylist disables plugins even if allowed", () => {
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
const plugin = writePlugin({
|
||||
id: "blocked",
|
||||
body: `export default { id: "blocked", register() {} };`,
|
||||
});
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
workspaceDir: plugin.dir,
|
||||
config: {
|
||||
@@ -257,13 +257,13 @@ describe("loadMoltbotPlugins", () => {
|
||||
});
|
||||
|
||||
it("fails fast on invalid plugin config", () => {
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
const plugin = writePlugin({
|
||||
id: "configurable",
|
||||
body: `export default { id: "configurable", register() {} };`,
|
||||
});
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
workspaceDir: plugin.dir,
|
||||
config: {
|
||||
@@ -284,7 +284,7 @@ describe("loadMoltbotPlugins", () => {
|
||||
});
|
||||
|
||||
it("registers channel plugins", () => {
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
const plugin = writePlugin({
|
||||
id: "channel-demo",
|
||||
body: `export default { id: "channel-demo", register(api) {
|
||||
@@ -309,7 +309,7 @@ describe("loadMoltbotPlugins", () => {
|
||||
} };`,
|
||||
});
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
workspaceDir: plugin.dir,
|
||||
config: {
|
||||
@@ -325,7 +325,7 @@ describe("loadMoltbotPlugins", () => {
|
||||
});
|
||||
|
||||
it("registers http handlers", () => {
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
const plugin = writePlugin({
|
||||
id: "http-demo",
|
||||
body: `export default { id: "http-demo", register(api) {
|
||||
@@ -333,7 +333,7 @@ describe("loadMoltbotPlugins", () => {
|
||||
} };`,
|
||||
});
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
workspaceDir: plugin.dir,
|
||||
config: {
|
||||
@@ -351,7 +351,7 @@ describe("loadMoltbotPlugins", () => {
|
||||
});
|
||||
|
||||
it("registers http routes", () => {
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
const plugin = writePlugin({
|
||||
id: "http-route-demo",
|
||||
body: `export default { id: "http-route-demo", register(api) {
|
||||
@@ -359,7 +359,7 @@ describe("loadMoltbotPlugins", () => {
|
||||
} };`,
|
||||
});
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
workspaceDir: plugin.dir,
|
||||
config: {
|
||||
@@ -378,13 +378,13 @@ describe("loadMoltbotPlugins", () => {
|
||||
});
|
||||
|
||||
it("respects explicit disable in config", () => {
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
const plugin = writePlugin({
|
||||
id: "config-disable",
|
||||
body: `export default { id: "config-disable", register() {} };`,
|
||||
});
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
config: {
|
||||
plugins: {
|
||||
@@ -401,7 +401,7 @@ describe("loadMoltbotPlugins", () => {
|
||||
});
|
||||
|
||||
it("enforces memory slot selection", () => {
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
const memoryA = writePlugin({
|
||||
id: "memory-a",
|
||||
body: `export default { id: "memory-a", kind: "memory", register() {} };`,
|
||||
@@ -411,7 +411,7 @@ describe("loadMoltbotPlugins", () => {
|
||||
body: `export default { id: "memory-b", kind: "memory", register() {} };`,
|
||||
});
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
config: {
|
||||
plugins: {
|
||||
@@ -428,13 +428,13 @@ describe("loadMoltbotPlugins", () => {
|
||||
});
|
||||
|
||||
it("disables memory plugins when slot is none", () => {
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = "/nonexistent/bundled/plugins";
|
||||
const memory = writePlugin({
|
||||
id: "memory-off",
|
||||
body: `export default { id: "memory-off", kind: "memory", register() {} };`,
|
||||
});
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
config: {
|
||||
plugins: {
|
||||
@@ -456,14 +456,14 @@ describe("loadMoltbotPlugins", () => {
|
||||
dir: bundledDir,
|
||||
filename: "shadow.js",
|
||||
});
|
||||
process.env.CLAWDBOT_BUNDLED_PLUGINS_DIR = bundledDir;
|
||||
process.env.OPENCLAW_BUNDLED_PLUGINS_DIR = bundledDir;
|
||||
|
||||
const override = writePlugin({
|
||||
id: "shadow",
|
||||
body: `export default { id: "shadow", register() {} };`,
|
||||
});
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
cache: false,
|
||||
config: {
|
||||
plugins: {
|
||||
|
||||
@@ -3,14 +3,13 @@ import path from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import { createJiti } from "jiti";
|
||||
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { GatewayRequestHandler } from "../gateway/server-methods/types.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { discoverMoltbotPlugins } from "./discovery.js";
|
||||
import { discoverOpenClawPlugins } from "./discovery.js";
|
||||
import { loadPluginManifestRegistry } from "./manifest-registry.js";
|
||||
import {
|
||||
applyTestPluginDefaults,
|
||||
normalizePluginsConfig,
|
||||
resolveEnableState,
|
||||
resolveMemorySlotDecision,
|
||||
@@ -23,8 +22,8 @@ import { createPluginRuntime } from "./runtime/index.js";
|
||||
import { setActivePluginRegistry } from "./runtime.js";
|
||||
import { validateJsonSchemaValue } from "./schema-validator.js";
|
||||
import type {
|
||||
MoltbotPluginDefinition,
|
||||
MoltbotPluginModule,
|
||||
OpenClawPluginDefinition,
|
||||
OpenClawPluginModule,
|
||||
PluginDiagnostic,
|
||||
PluginLogger,
|
||||
} from "./types.js";
|
||||
@@ -32,7 +31,7 @@ import type {
|
||||
export type PluginLoadResult = PluginRegistry;
|
||||
|
||||
export type PluginLoadOptions = {
|
||||
config?: MoltbotConfig;
|
||||
config?: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
logger?: PluginLogger;
|
||||
coreGatewayHandlers?: Record<string, GatewayRequestHandler>;
|
||||
@@ -99,8 +98,8 @@ function validatePluginConfig(params: {
|
||||
}
|
||||
|
||||
function resolvePluginModuleExport(moduleExport: unknown): {
|
||||
definition?: MoltbotPluginDefinition;
|
||||
register?: MoltbotPluginDefinition["register"];
|
||||
definition?: OpenClawPluginDefinition;
|
||||
register?: OpenClawPluginDefinition["register"];
|
||||
} {
|
||||
const resolved =
|
||||
moduleExport &&
|
||||
@@ -110,11 +109,11 @@ function resolvePluginModuleExport(moduleExport: unknown): {
|
||||
: moduleExport;
|
||||
if (typeof resolved === "function") {
|
||||
return {
|
||||
register: resolved as MoltbotPluginDefinition["register"],
|
||||
register: resolved as OpenClawPluginDefinition["register"],
|
||||
};
|
||||
}
|
||||
if (resolved && typeof resolved === "object") {
|
||||
const def = resolved as MoltbotPluginDefinition;
|
||||
const def = resolved as OpenClawPluginDefinition;
|
||||
const register = def.register ?? def.activate;
|
||||
return { definition: def, register };
|
||||
}
|
||||
@@ -162,8 +161,8 @@ function pushDiagnostics(diagnostics: PluginDiagnostic[], append: PluginDiagnost
|
||||
diagnostics.push(...append);
|
||||
}
|
||||
|
||||
export function loadMoltbotPlugins(options: PluginLoadOptions = {}): PluginRegistry {
|
||||
const cfg = applyTestPluginDefaults(options.config ?? {});
|
||||
export function loadOpenClawPlugins(options: PluginLoadOptions = {}): PluginRegistry {
|
||||
const cfg = options.config ?? {};
|
||||
const logger = options.logger ?? defaultLogger();
|
||||
const validateOnly = options.mode === "validate";
|
||||
const normalized = normalizePluginsConfig(cfg.plugins);
|
||||
@@ -190,7 +189,7 @@ export function loadMoltbotPlugins(options: PluginLoadOptions = {}): PluginRegis
|
||||
coreGatewayHandlers: options.coreGatewayHandlers as Record<string, GatewayRequestHandler>,
|
||||
});
|
||||
|
||||
const discovery = discoverMoltbotPlugins({
|
||||
const discovery = discoverOpenClawPlugins({
|
||||
workspaceDir: options.workspaceDir,
|
||||
extraPaths: normalized.loadPaths,
|
||||
});
|
||||
@@ -209,10 +208,7 @@ export function loadMoltbotPlugins(options: PluginLoadOptions = {}): PluginRegis
|
||||
extensions: [".ts", ".tsx", ".mts", ".cts", ".mtsx", ".ctsx", ".js", ".mjs", ".cjs", ".json"],
|
||||
...(pluginSdkAlias
|
||||
? {
|
||||
alias: {
|
||||
"clawdbot/plugin-sdk": pluginSdkAlias,
|
||||
"moltbot/plugin-sdk": pluginSdkAlias,
|
||||
},
|
||||
alias: { "openclaw/plugin-sdk": pluginSdkAlias },
|
||||
}
|
||||
: {}),
|
||||
});
|
||||
@@ -290,9 +286,9 @@ export function loadMoltbotPlugins(options: PluginLoadOptions = {}): PluginRegis
|
||||
continue;
|
||||
}
|
||||
|
||||
let mod: MoltbotPluginModule | null = null;
|
||||
let mod: OpenClawPluginModule | null = null;
|
||||
try {
|
||||
mod = jiti(candidate.source) as MoltbotPluginModule;
|
||||
mod = jiti(candidate.source) as OpenClawPluginModule;
|
||||
} catch (err) {
|
||||
logger.error(`[plugins] ${record.id} failed to load from ${record.source}: ${String(err)}`);
|
||||
record.status = "error";
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import fs from "node:fs";
|
||||
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { normalizePluginsConfig, type NormalizedPluginsConfig } from "./config-state.js";
|
||||
import { discoverMoltbotPlugins, type PluginCandidate } from "./discovery.js";
|
||||
import { discoverOpenClawPlugins, type PluginCandidate } from "./discovery.js";
|
||||
import { loadPluginManifest, type PluginManifest } from "./manifest.js";
|
||||
import type { PluginConfigUiHint, PluginDiagnostic, PluginKind, PluginOrigin } from "./types.js";
|
||||
|
||||
@@ -36,7 +36,7 @@ const registryCache = new Map<string, { expiresAt: number; registry: PluginManif
|
||||
const DEFAULT_MANIFEST_CACHE_MS = 200;
|
||||
|
||||
function resolveManifestCacheMs(env: NodeJS.ProcessEnv): number {
|
||||
const raw = env.CLAWDBOT_PLUGIN_MANIFEST_CACHE_MS?.trim();
|
||||
const raw = env.OPENCLAW_PLUGIN_MANIFEST_CACHE_MS?.trim();
|
||||
if (raw === "" || raw === "0") return 0;
|
||||
if (!raw) return DEFAULT_MANIFEST_CACHE_MS;
|
||||
const parsed = Number.parseInt(raw, 10);
|
||||
@@ -45,7 +45,7 @@ function resolveManifestCacheMs(env: NodeJS.ProcessEnv): number {
|
||||
}
|
||||
|
||||
function shouldUseManifestCache(env: NodeJS.ProcessEnv): boolean {
|
||||
const disabled = env.CLAWDBOT_DISABLE_PLUGIN_MANIFEST_CACHE?.trim();
|
||||
const disabled = env.OPENCLAW_DISABLE_PLUGIN_MANIFEST_CACHE?.trim();
|
||||
if (disabled) return false;
|
||||
return resolveManifestCacheMs(env) > 0;
|
||||
}
|
||||
@@ -100,7 +100,7 @@ function buildRecord(params: {
|
||||
}
|
||||
|
||||
export function loadPluginManifestRegistry(params: {
|
||||
config?: MoltbotConfig;
|
||||
config?: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
cache?: boolean;
|
||||
env?: NodeJS.ProcessEnv;
|
||||
@@ -122,7 +122,7 @@ export function loadPluginManifestRegistry(params: {
|
||||
candidates: params.candidates,
|
||||
diagnostics: params.diagnostics ?? [],
|
||||
}
|
||||
: discoverMoltbotPlugins({
|
||||
: discoverOpenClawPlugins({
|
||||
workspaceDir: params.workspaceDir,
|
||||
extraPaths: normalized.loadPaths,
|
||||
});
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
import fs from "node:fs";
|
||||
import path from "node:path";
|
||||
|
||||
import { LEGACY_MANIFEST_KEY, LEGACY_PLUGIN_MANIFEST_FILENAME } from "../compat/legacy-names.js";
|
||||
import { MANIFEST_KEY } from "../compat/legacy-names.js";
|
||||
import type { PluginConfigUiHint, PluginKind } from "./types.js";
|
||||
|
||||
export const PLUGIN_MANIFEST_FILENAME = "moltbot.plugin.json";
|
||||
export const PLUGIN_MANIFEST_FILENAMES = [
|
||||
PLUGIN_MANIFEST_FILENAME,
|
||||
LEGACY_PLUGIN_MANIFEST_FILENAME,
|
||||
] as const;
|
||||
export const PLUGIN_MANIFEST_FILENAME = "openclaw.plugin.json";
|
||||
export const PLUGIN_MANIFEST_FILENAMES = [PLUGIN_MANIFEST_FILENAME] as const;
|
||||
|
||||
export type PluginManifest = {
|
||||
id: string;
|
||||
@@ -102,7 +99,7 @@ export function loadPluginManifest(rootDir: string): PluginManifestLoadResult {
|
||||
};
|
||||
}
|
||||
|
||||
// package.json "moltbot" metadata (used for onboarding/catalog)
|
||||
// package.json "openclaw" metadata (used for onboarding/catalog)
|
||||
export type PluginPackageChannel = {
|
||||
id?: string;
|
||||
label?: string;
|
||||
@@ -130,23 +127,23 @@ export type PluginPackageInstall = {
|
||||
defaultChoice?: "npm" | "local";
|
||||
};
|
||||
|
||||
export type MoltbotPackageManifest = {
|
||||
export type OpenClawPackageManifest = {
|
||||
extensions?: string[];
|
||||
channel?: PluginPackageChannel;
|
||||
install?: PluginPackageInstall;
|
||||
};
|
||||
|
||||
export type ManifestKey = typeof MANIFEST_KEY;
|
||||
|
||||
export type PackageManifest = {
|
||||
name?: string;
|
||||
version?: string;
|
||||
description?: string;
|
||||
moltbot?: MoltbotPackageManifest;
|
||||
[LEGACY_MANIFEST_KEY]?: MoltbotPackageManifest;
|
||||
};
|
||||
} & Partial<Record<ManifestKey, OpenClawPackageManifest>>;
|
||||
|
||||
export function getPackageManifestMetadata(
|
||||
manifest: PackageManifest | undefined,
|
||||
): MoltbotPackageManifest | undefined {
|
||||
): OpenClawPackageManifest | undefined {
|
||||
if (!manifest) return undefined;
|
||||
return manifest.moltbot ?? manifest[LEGACY_MANIFEST_KEY];
|
||||
return manifest[MANIFEST_KEY];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { loadMoltbotPlugins, type PluginLoadOptions } from "./loader.js";
|
||||
import { loadOpenClawPlugins, type PluginLoadOptions } from "./loader.js";
|
||||
import type { ProviderPlugin } from "./types.js";
|
||||
|
||||
const log = createSubsystemLogger("plugins");
|
||||
@@ -8,7 +8,7 @@ export function resolvePluginProviders(params: {
|
||||
config?: PluginLoadOptions["config"];
|
||||
workspaceDir?: string;
|
||||
}): ProviderPlugin[] {
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
logger: {
|
||||
|
||||
@@ -8,17 +8,17 @@ import type {
|
||||
import { registerInternalHook } from "../hooks/internal-hooks.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import type {
|
||||
MoltbotPluginApi,
|
||||
MoltbotPluginChannelRegistration,
|
||||
MoltbotPluginCliRegistrar,
|
||||
MoltbotPluginCommandDefinition,
|
||||
MoltbotPluginHttpHandler,
|
||||
MoltbotPluginHttpRouteHandler,
|
||||
MoltbotPluginHookOptions,
|
||||
OpenClawPluginApi,
|
||||
OpenClawPluginChannelRegistration,
|
||||
OpenClawPluginCliRegistrar,
|
||||
OpenClawPluginCommandDefinition,
|
||||
OpenClawPluginHttpHandler,
|
||||
OpenClawPluginHttpRouteHandler,
|
||||
OpenClawPluginHookOptions,
|
||||
ProviderPlugin,
|
||||
MoltbotPluginService,
|
||||
MoltbotPluginToolContext,
|
||||
MoltbotPluginToolFactory,
|
||||
OpenClawPluginService,
|
||||
OpenClawPluginToolContext,
|
||||
OpenClawPluginToolFactory,
|
||||
PluginConfigUiHint,
|
||||
PluginDiagnostic,
|
||||
PluginLogger,
|
||||
@@ -36,7 +36,7 @@ import { normalizePluginHttpPath } from "./http-path.js";
|
||||
|
||||
export type PluginToolRegistration = {
|
||||
pluginId: string;
|
||||
factory: MoltbotPluginToolFactory;
|
||||
factory: OpenClawPluginToolFactory;
|
||||
names: string[];
|
||||
optional: boolean;
|
||||
source: string;
|
||||
@@ -44,21 +44,21 @@ export type PluginToolRegistration = {
|
||||
|
||||
export type PluginCliRegistration = {
|
||||
pluginId: string;
|
||||
register: MoltbotPluginCliRegistrar;
|
||||
register: OpenClawPluginCliRegistrar;
|
||||
commands: string[];
|
||||
source: string;
|
||||
};
|
||||
|
||||
export type PluginHttpRegistration = {
|
||||
pluginId: string;
|
||||
handler: MoltbotPluginHttpHandler;
|
||||
handler: OpenClawPluginHttpHandler;
|
||||
source: string;
|
||||
};
|
||||
|
||||
export type PluginHttpRouteRegistration = {
|
||||
pluginId?: string;
|
||||
path: string;
|
||||
handler: MoltbotPluginHttpRouteHandler;
|
||||
handler: OpenClawPluginHttpRouteHandler;
|
||||
source?: string;
|
||||
};
|
||||
|
||||
@@ -84,13 +84,13 @@ export type PluginHookRegistration = {
|
||||
|
||||
export type PluginServiceRegistration = {
|
||||
pluginId: string;
|
||||
service: MoltbotPluginService;
|
||||
service: OpenClawPluginService;
|
||||
source: string;
|
||||
};
|
||||
|
||||
export type PluginCommandRegistration = {
|
||||
pluginId: string;
|
||||
command: MoltbotPluginCommandDefinition;
|
||||
command: OpenClawPluginCommandDefinition;
|
||||
source: string;
|
||||
};
|
||||
|
||||
@@ -167,13 +167,13 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
|
||||
const registerTool = (
|
||||
record: PluginRecord,
|
||||
tool: AnyAgentTool | MoltbotPluginToolFactory,
|
||||
tool: AnyAgentTool | OpenClawPluginToolFactory,
|
||||
opts?: { name?: string; names?: string[]; optional?: boolean },
|
||||
) => {
|
||||
const names = opts?.names ?? (opts?.name ? [opts.name] : []);
|
||||
const optional = opts?.optional === true;
|
||||
const factory: MoltbotPluginToolFactory =
|
||||
typeof tool === "function" ? tool : (_ctx: MoltbotPluginToolContext) => tool;
|
||||
const factory: OpenClawPluginToolFactory =
|
||||
typeof tool === "function" ? tool : (_ctx: OpenClawPluginToolContext) => tool;
|
||||
|
||||
if (typeof tool !== "function") {
|
||||
names.push(tool.name);
|
||||
@@ -196,8 +196,8 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
record: PluginRecord,
|
||||
events: string | string[],
|
||||
handler: Parameters<typeof registerInternalHook>[1],
|
||||
opts: MoltbotPluginHookOptions | undefined,
|
||||
config: MoltbotPluginApi["config"],
|
||||
opts: OpenClawPluginHookOptions | undefined,
|
||||
config: OpenClawPluginApi["config"],
|
||||
) => {
|
||||
const eventList = Array.isArray(events) ? events : [events];
|
||||
const normalizedEvents = eventList.map((event) => event.trim()).filter(Boolean);
|
||||
@@ -221,7 +221,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
...entry.hook,
|
||||
name,
|
||||
description,
|
||||
source: "moltbot-plugin",
|
||||
source: "openclaw-plugin",
|
||||
pluginId: record.id,
|
||||
},
|
||||
metadata: {
|
||||
@@ -233,7 +233,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
hook: {
|
||||
name,
|
||||
description,
|
||||
source: "moltbot-plugin",
|
||||
source: "openclaw-plugin",
|
||||
pluginId: record.id,
|
||||
filePath: record.source,
|
||||
baseDir: path.dirname(record.source),
|
||||
@@ -282,7 +282,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
record.gatewayMethods.push(trimmed);
|
||||
};
|
||||
|
||||
const registerHttpHandler = (record: PluginRecord, handler: MoltbotPluginHttpHandler) => {
|
||||
const registerHttpHandler = (record: PluginRecord, handler: OpenClawPluginHttpHandler) => {
|
||||
record.httpHandlers += 1;
|
||||
registry.httpHandlers.push({
|
||||
pluginId: record.id,
|
||||
@@ -293,7 +293,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
|
||||
const registerHttpRoute = (
|
||||
record: PluginRecord,
|
||||
params: { path: string; handler: MoltbotPluginHttpRouteHandler },
|
||||
params: { path: string; handler: OpenClawPluginHttpRouteHandler },
|
||||
) => {
|
||||
const normalizedPath = normalizePluginHttpPath(params.path);
|
||||
if (!normalizedPath) {
|
||||
@@ -325,11 +325,11 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
|
||||
const registerChannel = (
|
||||
record: PluginRecord,
|
||||
registration: MoltbotPluginChannelRegistration | ChannelPlugin,
|
||||
registration: OpenClawPluginChannelRegistration | ChannelPlugin,
|
||||
) => {
|
||||
const normalized =
|
||||
typeof (registration as MoltbotPluginChannelRegistration).plugin === "object"
|
||||
? (registration as MoltbotPluginChannelRegistration)
|
||||
typeof (registration as OpenClawPluginChannelRegistration).plugin === "object"
|
||||
? (registration as OpenClawPluginChannelRegistration)
|
||||
: { plugin: registration as ChannelPlugin };
|
||||
const plugin = normalized.plugin;
|
||||
const id = typeof plugin?.id === "string" ? plugin.id.trim() : String(plugin?.id ?? "").trim();
|
||||
@@ -382,7 +382,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
|
||||
const registerCli = (
|
||||
record: PluginRecord,
|
||||
registrar: MoltbotPluginCliRegistrar,
|
||||
registrar: OpenClawPluginCliRegistrar,
|
||||
opts?: { commands?: string[] },
|
||||
) => {
|
||||
const commands = (opts?.commands ?? []).map((cmd) => cmd.trim()).filter(Boolean);
|
||||
@@ -395,7 +395,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
});
|
||||
};
|
||||
|
||||
const registerService = (record: PluginRecord, service: MoltbotPluginService) => {
|
||||
const registerService = (record: PluginRecord, service: OpenClawPluginService) => {
|
||||
const id = service.id.trim();
|
||||
if (!id) return;
|
||||
record.services.push(id);
|
||||
@@ -406,7 +406,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
});
|
||||
};
|
||||
|
||||
const registerCommand = (record: PluginRecord, command: MoltbotPluginCommandDefinition) => {
|
||||
const registerCommand = (record: PluginRecord, command: OpenClawPluginCommandDefinition) => {
|
||||
const name = command.name.trim();
|
||||
if (!name) {
|
||||
pushDiagnostic({
|
||||
@@ -464,10 +464,10 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
|
||||
const createApi = (
|
||||
record: PluginRecord,
|
||||
params: {
|
||||
config: MoltbotPluginApi["config"];
|
||||
config: OpenClawPluginApi["config"];
|
||||
pluginConfig?: Record<string, unknown>;
|
||||
},
|
||||
): MoltbotPluginApi => {
|
||||
): OpenClawPluginApi => {
|
||||
return {
|
||||
id: record.id,
|
||||
name: record.name,
|
||||
|
||||
@@ -16,7 +16,7 @@ const createEmptyRegistry = (): PluginRegistry => ({
|
||||
diagnostics: [],
|
||||
});
|
||||
|
||||
const REGISTRY_STATE = Symbol.for("moltbot.pluginRegistryState");
|
||||
const REGISTRY_STATE = Symbol.for("openclaw.pluginRegistryState");
|
||||
|
||||
type RegistryState = {
|
||||
registry: PluginRegistry | null;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { STATE_DIR } from "../config/paths.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import type { PluginRegistry } from "./registry.js";
|
||||
@@ -11,7 +11,7 @@ export type PluginServicesHandle = {
|
||||
|
||||
export async function startPluginServices(params: {
|
||||
registry: PluginRegistry;
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
}): Promise<PluginServicesHandle> {
|
||||
const running: Array<{
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { applyExclusiveSlotSelection } from "./slots.js";
|
||||
|
||||
describe("applyExclusiveSlotSelection", () => {
|
||||
it("selects the slot and disables other entries for the same kind", () => {
|
||||
const config: MoltbotConfig = {
|
||||
const config: OpenClawConfig = {
|
||||
plugins: {
|
||||
slots: { memory: "memory-core" },
|
||||
entries: {
|
||||
@@ -37,7 +37,7 @@ describe("applyExclusiveSlotSelection", () => {
|
||||
});
|
||||
|
||||
it("does nothing when the slot already matches", () => {
|
||||
const config: MoltbotConfig = {
|
||||
const config: OpenClawConfig = {
|
||||
plugins: {
|
||||
slots: { memory: "memory" },
|
||||
entries: {
|
||||
@@ -59,7 +59,7 @@ describe("applyExclusiveSlotSelection", () => {
|
||||
});
|
||||
|
||||
it("warns when the slot falls back to a default", () => {
|
||||
const config: MoltbotConfig = {
|
||||
const config: OpenClawConfig = {
|
||||
plugins: {
|
||||
entries: {
|
||||
memory: { enabled: true },
|
||||
@@ -81,7 +81,7 @@ describe("applyExclusiveSlotSelection", () => {
|
||||
});
|
||||
|
||||
it("skips changes when no exclusive slot applies", () => {
|
||||
const config: MoltbotConfig = {};
|
||||
const config: OpenClawConfig = {};
|
||||
const result = applyExclusiveSlotSelection({
|
||||
config,
|
||||
selectedId: "custom",
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { PluginSlotsConfig } from "../config/types.plugins.js";
|
||||
import type { PluginKind } from "./types.js";
|
||||
|
||||
@@ -27,13 +27,13 @@ export function defaultSlotIdForKey(slotKey: PluginSlotKey): string {
|
||||
}
|
||||
|
||||
export type SlotSelectionResult = {
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
warnings: string[];
|
||||
changed: boolean;
|
||||
};
|
||||
|
||||
export function applyExclusiveSlotSelection(params: {
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
selectedId: string;
|
||||
selectedKind?: PluginKind;
|
||||
registry?: { plugins: SlotPluginRecord[] };
|
||||
|
||||
@@ -2,7 +2,7 @@ import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent
|
||||
import { resolveDefaultAgentWorkspaceDir } from "../agents/workspace.js";
|
||||
import { loadConfig } from "../config/config.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { loadMoltbotPlugins } from "./loader.js";
|
||||
import { loadOpenClawPlugins } from "./loader.js";
|
||||
import type { PluginRegistry } from "./registry.js";
|
||||
|
||||
export type PluginStatusReport = PluginRegistry & {
|
||||
@@ -21,7 +21,7 @@ export function buildPluginStatusReport(params?: {
|
||||
: (resolveAgentWorkspaceDir(config, resolveDefaultAgentId(config)) ??
|
||||
resolveDefaultAgentWorkspaceDir());
|
||||
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
config,
|
||||
workspaceDir,
|
||||
logger: {
|
||||
|
||||
@@ -13,7 +13,7 @@ const tempDirs: string[] = [];
|
||||
const EMPTY_PLUGIN_SCHEMA = { type: "object", additionalProperties: false, properties: {} };
|
||||
|
||||
function makeTempDir() {
|
||||
const dir = path.join(os.tmpdir(), `moltbot-plugin-tools-${randomUUID()}`);
|
||||
const dir = path.join(os.tmpdir(), `openclaw-plugin-tools-${randomUUID()}`);
|
||||
fs.mkdirSync(dir, { recursive: true });
|
||||
tempDirs.push(dir);
|
||||
return dir;
|
||||
@@ -24,7 +24,7 @@ function writePlugin(params: { id: string; body: string }): TempPlugin {
|
||||
const file = path.join(dir, `${params.id}.js`);
|
||||
fs.writeFileSync(file, params.body, "utf-8");
|
||||
fs.writeFileSync(
|
||||
path.join(dir, "moltbot.plugin.json"),
|
||||
path.join(dir, "openclaw.plugin.json"),
|
||||
JSON.stringify(
|
||||
{
|
||||
id: params.id,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import type { AnyAgentTool } from "../agents/tools/common.js";
|
||||
import { normalizeToolName } from "../agents/tool-policy.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { loadMoltbotPlugins } from "./loader.js";
|
||||
import type { MoltbotPluginToolContext } from "./types.js";
|
||||
import { loadOpenClawPlugins } from "./loader.js";
|
||||
import type { OpenClawPluginToolContext } from "./types.js";
|
||||
|
||||
const log = createSubsystemLogger("plugins");
|
||||
|
||||
@@ -35,11 +35,11 @@ function isOptionalToolAllowed(params: {
|
||||
}
|
||||
|
||||
export function resolvePluginTools(params: {
|
||||
context: MoltbotPluginToolContext;
|
||||
context: OpenClawPluginToolContext;
|
||||
existingToolNames?: Set<string>;
|
||||
toolAllowlist?: string[];
|
||||
}): AnyAgentTool[] {
|
||||
const registry = loadMoltbotPlugins({
|
||||
const registry = loadOpenClawPlugins({
|
||||
config: params.context.config,
|
||||
workspaceDir: params.context.workspaceDir,
|
||||
logger: {
|
||||
|
||||
@@ -7,7 +7,7 @@ import type { AuthProfileCredential, OAuthCredential } from "../agents/auth-prof
|
||||
import type { AnyAgentTool } from "../agents/tools/common.js";
|
||||
import type { ChannelDock } from "../channels/dock.js";
|
||||
import type { ChannelPlugin } from "../channels/plugins/types.js";
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { InternalHookHandler } from "../hooks/internal-hooks.js";
|
||||
import type { HookEntry } from "../hooks/types.js";
|
||||
import type { ModelProviderConfig } from "../config/types.js";
|
||||
@@ -41,7 +41,7 @@ export type PluginConfigValidation =
|
||||
| { ok: true; value?: unknown }
|
||||
| { ok: false; errors: string[] };
|
||||
|
||||
export type MoltbotPluginConfigSchema = {
|
||||
export type OpenClawPluginConfigSchema = {
|
||||
safeParse?: (value: unknown) => {
|
||||
success: boolean;
|
||||
data?: unknown;
|
||||
@@ -55,8 +55,8 @@ export type MoltbotPluginConfigSchema = {
|
||||
jsonSchema?: Record<string, unknown>;
|
||||
};
|
||||
|
||||
export type MoltbotPluginToolContext = {
|
||||
config?: MoltbotConfig;
|
||||
export type OpenClawPluginToolContext = {
|
||||
config?: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
agentDir?: string;
|
||||
agentId?: string;
|
||||
@@ -66,17 +66,17 @@ export type MoltbotPluginToolContext = {
|
||||
sandboxed?: boolean;
|
||||
};
|
||||
|
||||
export type MoltbotPluginToolFactory = (
|
||||
ctx: MoltbotPluginToolContext,
|
||||
export type OpenClawPluginToolFactory = (
|
||||
ctx: OpenClawPluginToolContext,
|
||||
) => AnyAgentTool | AnyAgentTool[] | null | undefined;
|
||||
|
||||
export type MoltbotPluginToolOptions = {
|
||||
export type OpenClawPluginToolOptions = {
|
||||
name?: string;
|
||||
names?: string[];
|
||||
optional?: boolean;
|
||||
};
|
||||
|
||||
export type MoltbotPluginHookOptions = {
|
||||
export type OpenClawPluginHookOptions = {
|
||||
entry?: HookEntry;
|
||||
name?: string;
|
||||
description?: string;
|
||||
@@ -87,13 +87,13 @@ export type ProviderAuthKind = "oauth" | "api_key" | "token" | "device_code" | "
|
||||
|
||||
export type ProviderAuthResult = {
|
||||
profiles: Array<{ profileId: string; credential: AuthProfileCredential }>;
|
||||
configPatch?: Partial<MoltbotConfig>;
|
||||
configPatch?: Partial<OpenClawConfig>;
|
||||
defaultModel?: string;
|
||||
notes?: string[];
|
||||
};
|
||||
|
||||
export type ProviderAuthContext = {
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
agentDir?: string;
|
||||
workspaceDir?: string;
|
||||
prompter: WizardPrompter;
|
||||
@@ -125,7 +125,7 @@ export type ProviderPlugin = {
|
||||
refreshOAuth?: (cred: OAuthCredential) => Promise<OAuthCredential>;
|
||||
};
|
||||
|
||||
export type MoltbotPluginGatewayMethod = {
|
||||
export type OpenClawPluginGatewayMethod = {
|
||||
method: string;
|
||||
handler: GatewayRequestHandler;
|
||||
};
|
||||
@@ -148,8 +148,8 @@ export type PluginCommandContext = {
|
||||
args?: string;
|
||||
/** The full normalized command body */
|
||||
commandBody: string;
|
||||
/** Current moltbot configuration */
|
||||
config: MoltbotConfig;
|
||||
/** Current OpenClaw configuration */
|
||||
config: OpenClawConfig;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -167,7 +167,7 @@ export type PluginCommandHandler = (
|
||||
/**
|
||||
* Definition for a plugin-registered command.
|
||||
*/
|
||||
export type MoltbotPluginCommandDefinition = {
|
||||
export type OpenClawPluginCommandDefinition = {
|
||||
/** Command name without leading slash (e.g., "tts") */
|
||||
name: string;
|
||||
/** Description shown in /help and command menus */
|
||||
@@ -180,90 +180,90 @@ export type MoltbotPluginCommandDefinition = {
|
||||
handler: PluginCommandHandler;
|
||||
};
|
||||
|
||||
export type MoltbotPluginHttpHandler = (
|
||||
export type OpenClawPluginHttpHandler = (
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
) => Promise<boolean> | boolean;
|
||||
|
||||
export type MoltbotPluginHttpRouteHandler = (
|
||||
export type OpenClawPluginHttpRouteHandler = (
|
||||
req: IncomingMessage,
|
||||
res: ServerResponse,
|
||||
) => Promise<void> | void;
|
||||
|
||||
export type MoltbotPluginCliContext = {
|
||||
export type OpenClawPluginCliContext = {
|
||||
program: Command;
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
logger: PluginLogger;
|
||||
};
|
||||
|
||||
export type MoltbotPluginCliRegistrar = (ctx: MoltbotPluginCliContext) => void | Promise<void>;
|
||||
export type OpenClawPluginCliRegistrar = (ctx: OpenClawPluginCliContext) => void | Promise<void>;
|
||||
|
||||
export type MoltbotPluginServiceContext = {
|
||||
config: MoltbotConfig;
|
||||
export type OpenClawPluginServiceContext = {
|
||||
config: OpenClawConfig;
|
||||
workspaceDir?: string;
|
||||
stateDir: string;
|
||||
logger: PluginLogger;
|
||||
};
|
||||
|
||||
export type MoltbotPluginService = {
|
||||
export type OpenClawPluginService = {
|
||||
id: string;
|
||||
start: (ctx: MoltbotPluginServiceContext) => void | Promise<void>;
|
||||
stop?: (ctx: MoltbotPluginServiceContext) => void | Promise<void>;
|
||||
start: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;
|
||||
stop?: (ctx: OpenClawPluginServiceContext) => void | Promise<void>;
|
||||
};
|
||||
|
||||
export type MoltbotPluginChannelRegistration = {
|
||||
export type OpenClawPluginChannelRegistration = {
|
||||
plugin: ChannelPlugin;
|
||||
dock?: ChannelDock;
|
||||
};
|
||||
|
||||
export type MoltbotPluginDefinition = {
|
||||
export type OpenClawPluginDefinition = {
|
||||
id?: string;
|
||||
name?: string;
|
||||
description?: string;
|
||||
version?: string;
|
||||
kind?: PluginKind;
|
||||
configSchema?: MoltbotPluginConfigSchema;
|
||||
register?: (api: MoltbotPluginApi) => void | Promise<void>;
|
||||
activate?: (api: MoltbotPluginApi) => void | Promise<void>;
|
||||
configSchema?: OpenClawPluginConfigSchema;
|
||||
register?: (api: OpenClawPluginApi) => void | Promise<void>;
|
||||
activate?: (api: OpenClawPluginApi) => void | Promise<void>;
|
||||
};
|
||||
|
||||
export type MoltbotPluginModule =
|
||||
| MoltbotPluginDefinition
|
||||
| ((api: MoltbotPluginApi) => void | Promise<void>);
|
||||
export type OpenClawPluginModule =
|
||||
| OpenClawPluginDefinition
|
||||
| ((api: OpenClawPluginApi) => void | Promise<void>);
|
||||
|
||||
export type MoltbotPluginApi = {
|
||||
export type OpenClawPluginApi = {
|
||||
id: string;
|
||||
name: string;
|
||||
version?: string;
|
||||
description?: string;
|
||||
source: string;
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
pluginConfig?: Record<string, unknown>;
|
||||
runtime: PluginRuntime;
|
||||
logger: PluginLogger;
|
||||
registerTool: (
|
||||
tool: AnyAgentTool | MoltbotPluginToolFactory,
|
||||
opts?: MoltbotPluginToolOptions,
|
||||
tool: AnyAgentTool | OpenClawPluginToolFactory,
|
||||
opts?: OpenClawPluginToolOptions,
|
||||
) => void;
|
||||
registerHook: (
|
||||
events: string | string[],
|
||||
handler: InternalHookHandler,
|
||||
opts?: MoltbotPluginHookOptions,
|
||||
opts?: OpenClawPluginHookOptions,
|
||||
) => void;
|
||||
registerHttpHandler: (handler: MoltbotPluginHttpHandler) => void;
|
||||
registerHttpRoute: (params: { path: string; handler: MoltbotPluginHttpRouteHandler }) => void;
|
||||
registerChannel: (registration: MoltbotPluginChannelRegistration | ChannelPlugin) => void;
|
||||
registerHttpHandler: (handler: OpenClawPluginHttpHandler) => void;
|
||||
registerHttpRoute: (params: { path: string; handler: OpenClawPluginHttpRouteHandler }) => void;
|
||||
registerChannel: (registration: OpenClawPluginChannelRegistration | ChannelPlugin) => void;
|
||||
registerGatewayMethod: (method: string, handler: GatewayRequestHandler) => void;
|
||||
registerCli: (registrar: MoltbotPluginCliRegistrar, opts?: { commands?: string[] }) => void;
|
||||
registerService: (service: MoltbotPluginService) => void;
|
||||
registerCli: (registrar: OpenClawPluginCliRegistrar, opts?: { commands?: string[] }) => void;
|
||||
registerService: (service: OpenClawPluginService) => void;
|
||||
registerProvider: (provider: ProviderPlugin) => void;
|
||||
/**
|
||||
* Register a custom command that bypasses the LLM agent.
|
||||
* Plugin commands are processed before built-in commands and before agent invocation.
|
||||
* Use this for simple state-toggling or status commands that don't need AI reasoning.
|
||||
*/
|
||||
registerCommand: (command: MoltbotPluginCommandDefinition) => void;
|
||||
registerCommand: (command: OpenClawPluginCommandDefinition) => void;
|
||||
resolvePath: (input: string) => string;
|
||||
/** Register a lifecycle hook handler */
|
||||
on: <K extends PluginHookName>(
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
import fs from "node:fs/promises";
|
||||
|
||||
import type { MoltbotConfig } from "../config/config.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { UpdateChannel } from "../infra/update-channels.js";
|
||||
import { resolveUserPath } from "../utils.js";
|
||||
import { discoverMoltbotPlugins } from "./discovery.js";
|
||||
import { discoverOpenClawPlugins } from "./discovery.js";
|
||||
import { installPluginFromNpmSpec, resolvePluginInstallDir } from "./install.js";
|
||||
import { recordPluginInstall } from "./installs.js";
|
||||
import { loadPluginManifest } from "./manifest.js";
|
||||
@@ -25,7 +25,7 @@ export type PluginUpdateOutcome = {
|
||||
};
|
||||
|
||||
export type PluginUpdateSummary = {
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
changed: boolean;
|
||||
outcomes: PluginUpdateOutcome[];
|
||||
};
|
||||
@@ -38,7 +38,7 @@ export type PluginChannelSyncSummary = {
|
||||
};
|
||||
|
||||
export type PluginChannelSyncResult = {
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
changed: boolean;
|
||||
summary: PluginChannelSyncSummary;
|
||||
};
|
||||
@@ -62,7 +62,7 @@ async function readInstalledPackageVersion(dir: string): Promise<string | undefi
|
||||
function resolveBundledPluginSources(params: {
|
||||
workspaceDir?: string;
|
||||
}): Map<string, BundledPluginSource> {
|
||||
const discovery = discoverMoltbotPlugins({ workspaceDir: params.workspaceDir });
|
||||
const discovery = discoverOpenClawPlugins({ workspaceDir: params.workspaceDir });
|
||||
const bundled = new Map<string, BundledPluginSource>();
|
||||
|
||||
for (const candidate of discovery.candidates) {
|
||||
@@ -73,7 +73,7 @@ function resolveBundledPluginSources(params: {
|
||||
if (bundled.has(pluginId)) continue;
|
||||
|
||||
const npmSpec =
|
||||
candidate.packageMoltbot?.install?.npmSpec?.trim() ||
|
||||
candidate.packageManifest?.install?.npmSpec?.trim() ||
|
||||
candidate.packageName?.trim() ||
|
||||
undefined;
|
||||
|
||||
@@ -127,7 +127,7 @@ function buildLoadPathHelpers(existing: string[]) {
|
||||
}
|
||||
|
||||
export async function updateNpmInstalledPlugins(params: {
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
logger?: PluginUpdateLogger;
|
||||
pluginIds?: string[];
|
||||
skipIds?: Set<string>;
|
||||
@@ -290,7 +290,7 @@ export async function updateNpmInstalledPlugins(params: {
|
||||
}
|
||||
|
||||
export async function syncPluginsForUpdateChannel(params: {
|
||||
config: MoltbotConfig;
|
||||
config: OpenClawConfig;
|
||||
channel: UpdateChannel;
|
||||
workspaceDir?: string;
|
||||
logger?: PluginUpdateLogger;
|
||||
|
||||
Reference in New Issue
Block a user