diff --git a/nemoclaw/openclaw.plugin.json b/nemoclaw/openclaw.plugin.json index 7450d982851..342d8c2cc53 100644 --- a/nemoclaw/openclaw.plugin.json +++ b/nemoclaw/openclaw.plugin.json @@ -3,6 +3,15 @@ "name": "NemoClaw", "version": "0.1.0", "description": "Migrate and run OpenClaw inside OpenShell with optional NIM-backed inference", + "commandAliases": [ + { + "name": "nemoclaw", + "kind": "runtime-slash" + } + ], + "activation": { + "onStartup": true + }, "configSchema": { "type": "object", "properties": { diff --git a/schemas/openclaw-plugin.schema.json b/schemas/openclaw-plugin.schema.json index fd651e88fa6..80f3d748f89 100644 --- a/schemas/openclaw-plugin.schema.json +++ b/schemas/openclaw-plugin.schema.json @@ -4,7 +4,15 @@ "title": "NemoClaw OpenClaw Plugin Manifest", "description": "Schema for nemoclaw/openclaw.plugin.json — the OpenClaw plugin manifest that declares the plugin identity and its configuration schema.", "type": "object", - "required": ["id", "name", "version", "description", "configSchema"], + "required": [ + "id", + "name", + "version", + "description", + "commandAliases", + "activation", + "configSchema" + ], "additionalProperties": false, "properties": { "id": { @@ -27,6 +35,39 @@ "minLength": 1, "description": "Short description of the plugin." }, + "commandAliases": { + "type": "array", + "description": "Runtime command names that resolve to this plugin's handlers, such as chat slash commands.", + "items": { + "type": "object", + "required": ["name", "kind"], + "additionalProperties": false, + "properties": { + "name": { + "type": "string", + "minLength": 1, + "description": "Command name that belongs to this plugin." + }, + "kind": { + "type": "string", + "enum": ["runtime-slash"], + "description": "Marks the alias as a chat slash command rather than a root CLI command." + } + } + } + }, + "activation": { + "type": "object", + "description": "OpenClaw activation planner metadata. Use onStartup=true when plugin registration must run during Gateway startup.", + "required": ["onStartup"], + "additionalProperties": false, + "properties": { + "onStartup": { + "type": "boolean", + "description": "Whether OpenClaw should import the plugin during Gateway startup." + } + } + }, "configSchema": { "type": "object", "description": "JSON Schema object describing the plugin's configuration fields." diff --git a/test/validate-config-schemas.test.ts b/test/validate-config-schemas.test.ts index 0306ba20ece..221fbe4c305 100644 --- a/test/validate-config-schemas.test.ts +++ b/test/validate-config-schemas.test.ts @@ -515,12 +515,38 @@ describe("openclaw-plugin.schema.json", () => { name: "Fixture Plugin", version: "1.2.3", description: "Schema fixture", + configSchema: { type: "object" }, + commandAliases: [{ name: "fixture", kind: "runtime-slash" }], + activation: { onStartup: true }, }; it("openclaw.plugin.json passes schema validation", () => { expectValid(validate, data, "openclaw.plugin.json"); }); + it("accepts runtime slash activation metadata", () => { + expectValid(validate, validPluginFixture, "runtime slash activation fixture"); + }); + + it("rejects command alias without kind", () => { + const bad = { + ...validPluginFixture, + commandAliases: [{ name: "fixture" }], + activation: { onStartup: true }, + }; + expect(validate(bad)).toBe(false); + }); + + it("rejects empty activation metadata", () => { + const bad = { ...validPluginFixture, activation: {} }; + expect(validate(bad)).toBe(false); + }); + + it("rejects activation properties NemoClaw does not use", () => { + const bad = { ...validPluginFixture, activation: { onStartup: true, onProviders: ["demo"] } }; + expect(validate(bad)).toBe(false); + }); + it("rejects plugin with missing id", () => { const { id: _id, ...bad } = validPluginFixture; expect(validate(bad)).toBe(false);