mirror of https://github.com/openclaw/openclaw.git
Plugins: extract CLI lifecycle
This commit is contained in:
parent
565f9bf2bd
commit
b5757a6625
|
|
@ -0,0 +1,97 @@
|
|||
import { Command } from "commander";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { createEmptyPluginRegistry } from "../plugins/registry.js";
|
||||
import type { PluginLogger } from "../plugins/types.js";
|
||||
import { registerExtensionHostCliCommands } from "./cli-lifecycle.js";
|
||||
|
||||
function createLogger(): PluginLogger {
|
||||
return {
|
||||
info: vi.fn(),
|
||||
warn: vi.fn(),
|
||||
error: vi.fn(),
|
||||
debug: vi.fn(),
|
||||
};
|
||||
}
|
||||
|
||||
describe("registerExtensionHostCliCommands", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("skips overlapping command registrations", () => {
|
||||
const program = new Command();
|
||||
program.command("memory");
|
||||
const registry = createEmptyPluginRegistry();
|
||||
const memoryRegister = vi.fn();
|
||||
const otherRegister = vi.fn();
|
||||
registry.cliRegistrars.push(
|
||||
{
|
||||
pluginId: "memory-core",
|
||||
register: memoryRegister,
|
||||
commands: ["memory"],
|
||||
source: "bundled",
|
||||
},
|
||||
{
|
||||
pluginId: "other",
|
||||
register: otherRegister,
|
||||
commands: ["other"],
|
||||
source: "bundled",
|
||||
},
|
||||
);
|
||||
const logger = createLogger();
|
||||
|
||||
registerExtensionHostCliCommands({
|
||||
program,
|
||||
registry,
|
||||
config: {} as never,
|
||||
workspaceDir: "/tmp/workspace",
|
||||
logger,
|
||||
});
|
||||
|
||||
expect(memoryRegister).not.toHaveBeenCalled();
|
||||
expect(otherRegister).toHaveBeenCalledOnce();
|
||||
expect(logger.debug).toHaveBeenCalledWith(
|
||||
"plugin CLI register skipped (memory-core): command already registered (memory)",
|
||||
);
|
||||
});
|
||||
|
||||
it("warns on sync and async registration failures", async () => {
|
||||
const program = new Command();
|
||||
const registry = createEmptyPluginRegistry();
|
||||
registry.cliRegistrars.push(
|
||||
{
|
||||
pluginId: "sync-fail",
|
||||
register: () => {
|
||||
throw new Error("sync fail");
|
||||
},
|
||||
commands: ["sync"],
|
||||
source: "bundled",
|
||||
},
|
||||
{
|
||||
pluginId: "async-fail",
|
||||
register: async () => {
|
||||
throw new Error("async fail");
|
||||
},
|
||||
commands: ["async"],
|
||||
source: "bundled",
|
||||
},
|
||||
);
|
||||
const logger = createLogger();
|
||||
|
||||
registerExtensionHostCliCommands({
|
||||
program,
|
||||
registry,
|
||||
config: {} as never,
|
||||
workspaceDir: "/tmp/workspace",
|
||||
logger,
|
||||
});
|
||||
await Promise.resolve();
|
||||
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
"plugin CLI register failed (sync-fail): Error: sync fail",
|
||||
);
|
||||
expect(logger.warn).toHaveBeenCalledWith(
|
||||
"plugin CLI register failed (async-fail): Error: async fail",
|
||||
);
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
import type { Command } from "commander";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import type { PluginRegistry } from "../plugins/registry.js";
|
||||
import type { PluginLogger } from "../plugins/types.js";
|
||||
|
||||
export function registerExtensionHostCliCommands(params: {
|
||||
program: Command;
|
||||
registry: PluginRegistry;
|
||||
config: OpenClawConfig;
|
||||
workspaceDir: string;
|
||||
logger: PluginLogger;
|
||||
}): void {
|
||||
const existingCommands = new Set(params.program.commands.map((cmd) => cmd.name()));
|
||||
|
||||
for (const entry of params.registry.cliRegistrars) {
|
||||
if (entry.commands.length > 0) {
|
||||
const overlaps = entry.commands.filter((command) => existingCommands.has(command));
|
||||
if (overlaps.length > 0) {
|
||||
params.logger.debug(
|
||||
`plugin CLI register skipped (${entry.pluginId}): command already registered (${overlaps.join(
|
||||
", ",
|
||||
)})`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
const result = entry.register({
|
||||
program: params.program,
|
||||
config: params.config,
|
||||
workspaceDir: params.workspaceDir,
|
||||
logger: params.logger,
|
||||
});
|
||||
if (result && typeof result.then === "function") {
|
||||
void result.catch((err) => {
|
||||
params.logger.warn(`plugin CLI register failed (${entry.pluginId}): ${String(err)}`);
|
||||
});
|
||||
}
|
||||
for (const command of entry.commands) {
|
||||
existingCommands.add(command);
|
||||
}
|
||||
} catch (err) {
|
||||
params.logger.warn(`plugin CLI register failed (${entry.pluginId}): ${String(err)}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ import type { Command } from "commander";
|
|||
import { resolveAgentWorkspaceDir, resolveDefaultAgentId } from "../agents/agent-scope.js";
|
||||
import type { OpenClawConfig } from "../config/config.js";
|
||||
import { loadConfig } from "../config/config.js";
|
||||
import { registerExtensionHostCliCommands } from "../extension-host/cli-lifecycle.js";
|
||||
import { createSubsystemLogger } from "../logging/subsystem.js";
|
||||
import { loadOpenClawPlugins } from "./loader.js";
|
||||
import type { PluginLogger } from "./types.js";
|
||||
|
|
@ -27,38 +28,11 @@ export function registerPluginCliCommands(
|
|||
env,
|
||||
logger,
|
||||
});
|
||||
|
||||
const existingCommands = new Set(program.commands.map((cmd) => cmd.name()));
|
||||
|
||||
for (const entry of registry.cliRegistrars) {
|
||||
if (entry.commands.length > 0) {
|
||||
const overlaps = entry.commands.filter((command) => existingCommands.has(command));
|
||||
if (overlaps.length > 0) {
|
||||
log.debug(
|
||||
`plugin CLI register skipped (${entry.pluginId}): command already registered (${overlaps.join(
|
||||
", ",
|
||||
)})`,
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
const result = entry.register({
|
||||
program,
|
||||
config,
|
||||
workspaceDir,
|
||||
logger,
|
||||
});
|
||||
if (result && typeof result.then === "function") {
|
||||
void result.catch((err) => {
|
||||
log.warn(`plugin CLI register failed (${entry.pluginId}): ${String(err)}`);
|
||||
});
|
||||
}
|
||||
for (const command of entry.commands) {
|
||||
existingCommands.add(command);
|
||||
}
|
||||
} catch (err) {
|
||||
log.warn(`plugin CLI register failed (${entry.pluginId}): ${String(err)}`);
|
||||
}
|
||||
}
|
||||
registerExtensionHostCliCommands({
|
||||
program,
|
||||
registry,
|
||||
config,
|
||||
workspaceDir,
|
||||
logger,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue