hooks: default hooks.internal.enabled to true so bundled hooks load on fresh installs

Made-with: Cursor
This commit is contained in:
joelnishanth 2026-03-27 13:08:32 -05:00 committed by Ayaan Zaidi
parent 3886b65ef2
commit f849b8de97
6 changed files with 37 additions and 9 deletions

View File

@ -167,7 +167,7 @@ export async function startGatewaySidecars(params: {
);
}
if (params.cfg.hooks?.internal?.enabled) {
if (params.cfg.hooks?.internal?.enabled !== false) {
setTimeout(() => {
const hookEvent = createInternalHookEvent("gateway", "startup", "gateway:startup", {
cfg: params.cfg,

View File

@ -121,7 +121,7 @@ describe("loader", () => {
expect(getRegisteredEventKeys()).not.toContain("command:new");
};
it("should return 0 when hooks are disabled or missing", async () => {
it("should return 0 when hooks are explicitly disabled", async () => {
for (const cfg of [
{
hooks: {
@ -130,7 +130,28 @@ describe("loader", () => {
},
},
} satisfies OpenClawConfig,
{
hooks: {
internal: {
enabled: false,
handlers: [],
},
},
} satisfies OpenClawConfig,
]) {
const count = await loadInternalHooks(cfg, tmpDir);
expect(count).toBe(0);
}
});
it("should treat missing hooks.internal.enabled as enabled (default-on)", async () => {
// Empty config should NOT skip loading — it should attempt discovery.
// With no discoverable hooks in the temp dir (bundled dir is overridden
// to /nonexistent), this returns 0 but does NOT bail at the guard.
for (const cfg of [
{} satisfies OpenClawConfig,
{ hooks: {} } satisfies OpenClawConfig,
{ hooks: { internal: {} } } satisfies OpenClawConfig,
]) {
const count = await loadInternalHooks(cfg, tmpDir);
expect(count).toBe(0);

View File

@ -65,8 +65,8 @@ export async function loadInternalHooks(
bundledHooksDir?: string;
},
): Promise<number> {
// Check if hooks are enabled
if (!cfg.hooks?.internal?.enabled) {
// Hooks are on by default; only skip when explicitly disabled.
if (cfg.hooks?.internal?.enabled === false) {
return 0;
}
@ -153,7 +153,7 @@ export async function loadInternalHooks(
}
// 2. Load legacy config handlers (backwards compatibility)
const handlers = cfg.hooks.internal.handlers ?? [];
const handlers = cfg.hooks?.internal?.handlers ?? [];
for (const handlerConfig of handlers) {
try {
// Legacy handler paths: keep them workspace-relative.

View File

@ -375,7 +375,7 @@ export function createPluginRegistry(registryParams: PluginRegistryParams) {
source: record.source,
});
const hookSystemEnabled = config?.hooks?.internal?.enabled === true;
const hookSystemEnabled = config?.hooks?.internal?.enabled !== false;
if (!hookSystemEnabled || opts?.register === false) {
return;
}

View File

@ -23,9 +23,16 @@ describe("collectAttackSurfaceSummaryFindings", () => {
expectedDetail: ["hooks.webhooks: enabled", "hooks.internal: enabled"],
},
{
name: "reports both hook systems as disabled when neither is configured",
name: "reports internal hooks as enabled by default and webhooks as disabled when neither is configured",
cfg: {} satisfies OpenClawConfig,
expectedDetail: ["hooks.webhooks: disabled", "hooks.internal: disabled"],
expectedDetail: ["hooks.webhooks: disabled", "hooks.internal: enabled"],
},
{
name: "reports internal hooks as disabled when explicitly set to false",
cfg: {
hooks: { internal: { enabled: false } },
} satisfies OpenClawConfig,
expectedDetail: ["hooks.internal: disabled"],
},
])("$name", ({ cfg, expectedDetail }) => {
const [finding] = collectAttackSurfaceSummaryFindings(cfg);

View File

@ -526,7 +526,7 @@ export function collectAttackSurfaceSummaryFindings(cfg: OpenClawConfig): Securi
const group = summarizeGroupPolicy(cfg);
const elevated = cfg.tools?.elevated?.enabled !== false;
const webhooksEnabled = cfg.hooks?.enabled === true;
const internalHooksEnabled = cfg.hooks?.internal?.enabled === true;
const internalHooksEnabled = cfg.hooks?.internal?.enabled !== false;
const browserEnabled = cfg.browser?.enabled ?? true;
const detail =