Skip to content

Commit 8b70ad0

Browse files
Merge pull request #507 from corbitsdev/cl-6714-honor-plugin-defaultenabled-for-agents-tools-still-require
Honor plugin defaultEnabled for agent profiles
2 parents 354df71 + 50ce120 commit 8b70ad0

3 files changed

Lines changed: 42 additions & 4 deletions

File tree

src/plugins/agent-plugins.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,4 +95,34 @@ describe("resolveAgentPluginProfiles", () => {
9595
const profiles = await resolveAgentPluginProfiles([mod], config);
9696
expect(profiles[0]!.source).toBe("claude");
9797
});
98+
99+
// Gating uses isPluginModuleEnabled (same as skills), not the bare
100+
// isPluginEnabled (settings-only) that tool plugins use for consent-gating.
101+
test("loads profiles from a repo plugin with defaultEnabled and no settings entry", async () => {
102+
const mod: PluginModule = {
103+
manifest: { id: "p1", name: "p1", kind: "agent", defaultEnabled: true },
104+
agentPlugin: { agents: [validProfile] },
105+
origin: "repo",
106+
};
107+
const profiles = await resolveAgentPluginProfiles([mod], {});
108+
expect(profiles.map((p) => p.id)).toEqual(["explorer"]);
109+
});
110+
111+
test("does not load profiles from a non-repo plugin with defaultEnabled and no settings entry", async () => {
112+
const mod: PluginModule = {
113+
manifest: { id: "p1", name: "p1", kind: "agent", defaultEnabled: true },
114+
agentPlugin: { agents: [validProfile] },
115+
origin: "user",
116+
};
117+
expect(await resolveAgentPluginProfiles([mod], {})).toEqual([]);
118+
});
119+
120+
test("explicit enabled: false overrides repo defaultEnabled", async () => {
121+
const mod: PluginModule = {
122+
manifest: { id: "p1", name: "p1", kind: "agent", defaultEnabled: true },
123+
agentPlugin: { agents: [validProfile] },
124+
origin: "repo",
125+
};
126+
expect(await resolveAgentPluginProfiles([mod], { p1: { enabled: false } })).toEqual([]);
127+
});
98128
});

src/plugins/agent-plugins.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import type { AgentProfile } from "../agent/profiles.js";
44
import { AgentProfileSchema } from "../agent/profiles.js";
55
import type { PluginModule } from "./loader.js";
66
import type { PluginConfig } from "../config/settings.js";
7-
import { isPluginEnabled } from "./register.js";
7+
import { isPluginModuleEnabled } from "./register.js";
88
import {
99
pluginWarningSink,
1010
type PluginLoadDiagnostics,
@@ -34,7 +34,12 @@ function resolveAgentProfileWarningHandler(
3434
// validated against the AgentProfileSchema so a malformed entry is skipped
3535
// rather than crashing the sub-agent dispatcher. Enabled-only gating (no
3636
// consent) is sufficient: an agent profile is configuration data (tier,
37-
// capabilities, role prompt), not in-process code execution.
37+
// capabilities, role prompt), not in-process code execution. Gating uses
38+
// isPluginModuleEnabled (same as skills), so a first-party repo plugin with
39+
// manifest.defaultEnabled loads its profiles without an explicit settings
40+
// entry. This differs from tool plugins (isToolPluginActive), which require
41+
// explicit enabled+consented in settings even for repo plugins, because a
42+
// tool plugin runs in-process code rather than declaring configuration data.
3843
//
3944
// Warnings fire whenever a profile is rejected so JS-plugin authors get the
4045
// same feedback loop data-only plugin authors already enjoy. Pass `diagnostics`
@@ -49,7 +54,7 @@ export async function resolveAgentPluginProfiles(
4954
for (const mod of modules) {
5055
if (mod.manifest?.kind !== "agent") continue;
5156
if (mod.agentPlugin === undefined) continue;
52-
if (!isPluginEnabled(config, mod.manifest.id)) continue;
57+
if (!isPluginModuleEnabled(mod, config)) continue;
5358

5459
const rawAgents = mod.agentPlugin.agents;
5560
if (!Array.isArray(rawAgents)) continue;

src/plugins/tool-plugins.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ export function collectToolPlugins(modules: PluginModule[]): ToolPluginCandidate
3636
}
3737

3838
// A tool plugin adds in-process agent capabilities, so it is wired in only when
39-
// the user has both enabled it AND given one-time consent.
39+
// the user has both enabled it AND given one-time consent. Unlike skills
40+
// (isPluginModuleEnabled) and agent profiles (resolveAgentPluginProfiles),
41+
// repo manifest.defaultEnabled never activates a tool plugin on its own — this
42+
// is intentional, not an oversight, until product intent changes.
4043
export function isToolPluginActive(config: Record<string, PluginConfig>, id: string): boolean {
4144
return config[id]?.enabled === true && config[id]?.consented === true;
4245
}

0 commit comments

Comments
 (0)