diff --git a/src/cli/plugins-authoring-command.test.ts b/src/cli/plugins-authoring-command.test.ts index 2d5c4a62d76..4653125fcb9 100644 --- a/src/cli/plugins-authoring-command.test.ts +++ b/src/cli/plugins-authoring-command.test.ts @@ -188,7 +188,7 @@ describe("plugin authoring commands", () => { name: "demo", openclaw: { setupEntry: "./setup.ts", - extensions: ["./src/index.ts"], + extensions: ["./src/other.ts", "./src/index.ts"], }, }); }); diff --git a/src/cli/plugins-authoring-command.ts b/src/cli/plugins-authoring-command.ts index 5dbea4e62c4..7bc408e8015 100644 --- a/src/cli/plugins-authoring-command.ts +++ b/src/cli/plugins-authoring-command.ts @@ -194,11 +194,15 @@ export function buildToolPluginPackageManifest(params: { !Array.isArray(params.packageManifest.openclaw) ? { ...(params.packageManifest.openclaw as JsonObject) } : {}; + const existingExtensions = Array.isArray(openclaw.extensions) + ? openclaw.extensions.filter((entry): entry is string => typeof entry === "string") + : []; + const extensions = [...new Set([...existingExtensions, params.entry])]; return { ...params.packageManifest, openclaw: { ...openclaw, - extensions: [params.entry], + extensions, }, }; } diff --git a/src/cli/program/register.subclis-core.ts b/src/cli/program/register.subclis-core.ts index 5763022febc..d76dee5a0a3 100644 --- a/src/cli/program/register.subclis-core.ts +++ b/src/cli/program/register.subclis-core.ts @@ -59,10 +59,11 @@ async function registerGatewayRunOnly(program: Command): Promise { async function registerSubCliWithPluginCommands( program: Command, + argv: string[], registerSubCli: () => Promise, pluginCliPosition: "before" | "after", ) { - const invocation = resolveCliArgvInvocation(process.argv); + const invocation = resolveCliArgvInvocation(argv); const shouldRegisterPluginCommands = !invocation.hasHelpOrVersion && resolveCliCommandPathPolicy(invocation.commandPath).loadPlugins !== "never"; @@ -204,9 +205,10 @@ const entrySpecs: readonly CommandGroupDescriptorSpec[] = [ ]), { commandNames: ["pairing"], - register: async (program) => { + register: async (program, argv) => { await registerSubCliWithPluginCommands( program, + argv, async () => { const mod = await import("../pairing-cli.js"); mod.registerPairingCli(program); @@ -217,9 +219,10 @@ const entrySpecs: readonly CommandGroupDescriptorSpec[] = [ }, { commandNames: ["plugins"], - register: async (program) => { + register: async (program, argv) => { await registerSubCliWithPluginCommands( program, + argv, async () => { const mod = await import("../plugins-cli.js"); mod.registerPluginsCli(program); diff --git a/src/cli/program/route-specs.ts b/src/cli/program/route-specs.ts index bc325be07b6..fac04f4828e 100644 --- a/src/cli/program/route-specs.ts +++ b/src/cli/program/route-specs.ts @@ -50,9 +50,7 @@ export const routedCommands: RouteSpec[] = cliCommandCatalog ): entry is CliCommandCatalogEntry & { route: { id: keyof typeof routedCommandDefinitions } } => Boolean(entry.route), ) - .map((entry) => - createParsedRoute({ - entry, - definition: routedCommandDefinitions[entry.route.id], - }), - ); + .flatMap((entry) => { + const definition = routedCommandDefinitions[entry.route.id]; + return definition ? [createParsedRoute({ entry, definition })] : []; + });