
















@@ -40,6 +40,16 @@ const losslessClawToolRegistry: PluginManifestCommandAliasRegistry = {
4040],
4141};
424243+const browserCommandAliasRegistry: PluginManifestCommandAliasRegistry = {
44+plugins: [
45+{
46+id: "browser",
47+enabledByDefault: true,
48+commandAliases: [{ name: "browser" }],
49+},
50+],
51+};
52+4353describe("isGatewayRunFastPathArgv", () => {
4454it("matches only plain gateway foreground starts without root options or help", () => {
4555expect(isGatewayRunFastPathArgv(["node", "openclaw", "gateway"])).toBe(true);
@@ -191,11 +201,15 @@ describe("shouldUseBrowserHelpFastPath", () => {
191201describe("resolveMissingPluginCommandMessage", () => {
192202it("explains plugins.allow misses for a bundled plugin command", () => {
193203expect(
194-resolveMissingPluginCommandMessage("browser", {
195-plugins: {
196-allow: ["quietchat"],
204+resolveMissingPluginCommandMessage(
205+"browser",
206+{
207+plugins: {
208+allow: ["quietchat"],
209+},
197210},
198-}),
211+{ registry: browserCommandAliasRegistry },
212+),
199213).toContain('`plugins.allow` excludes "browser"');
200214});
201215@@ -402,7 +416,7 @@ describe("resolveMissingPluginCommandMessage", () => {
402416expect(message).toContain('"lossless-claw"');
403417});
404418405-it("preserves the plugins.allow suggestion when the unknown name is not a plugin tool", () => {
419+it("returns null for unknown names excluded by plugins.allow", () => {
406420const message = resolveMissingPluginCommandMessage(
407421"totally-unknown",
408422{
@@ -412,14 +426,30 @@ describe("resolveMissingPluginCommandMessage", () => {
412426},
413427{ registry: losslessClawToolRegistry },
414428);
415-expect(message).not.toBeNull();
416-expect(message).toContain('`plugins.allow` excludes "totally-unknown"');
429+expect(message).toBeNull();
430+});
431+432+it("points metadata-only CLI roots in plugins.allow at their parent plugin", () => {
433+const message = resolveMissingPluginCommandMessage(
434+"qa",
435+{
436+plugins: {
437+allow: ["browser"],
438+},
439+},
440+{
441+resolveCliCommandSurfaceOwner: () => "qa-lab",
442+},
443+);
444+expect(message).toContain('"qa" is not a plugin');
445+expect(message).toContain('"qa-lab"');
446+expect(message).toContain('Add "qa-lab" to `plugins.allow` instead of "qa"');
417447});
418448419449it("does not attribute a tool to an owning plugin excluded by plugins.allow", () => {
420450// The owning plugin is denied via plugins.allow, so the manifest-declared
421-// tool is not available through the owning plugin. Fall through to the
422-// standard plugins.allow message instead of falsely attributing it.
451+// tool is not available through the owning plugin. Tool names are not CLI
452+// command surfaces, so do not suggest adding the tool name to plugins.allow.
423453const message = resolveMissingPluginCommandMessage(
424454"lcm_recent",
425455{
@@ -429,9 +459,7 @@ describe("resolveMissingPluginCommandMessage", () => {
429459},
430460{ registry: losslessClawToolRegistry },
431461);
432-expect(message).not.toBeNull();
433-expect(message).not.toContain("agent tool available");
434-expect(message).toContain('`plugins.allow` excludes "lcm_recent"');
462+expect(message).toBeNull();
435463});
436464437465it("does not attribute a tool to an owning plugin disabled via plugins.entries", () => {
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。