diff --git a/src/utils/websearch/hook-config.ts b/src/utils/websearch/hook-config.ts index 0e0c2831..ad88b0bb 100644 --- a/src/utils/websearch/hook-config.ts +++ b/src/utils/websearch/hook-config.ts @@ -130,7 +130,9 @@ export function ensureHookConfig(): boolean { const command = hookArray?.[0]?.command; if (typeof command !== 'string') return false; - const normalized = command.replace(/\\/g, '/'); + const normalized = command + .replace(/\\/g, '/') // Windows backslashes + .replace(/\/+/g, '/'); // Collapse multiple slashes return normalized.includes('.ccs/hooks/websearch-transformer'); }); @@ -254,7 +256,9 @@ export function removeHookConfig(): boolean { const command = hookArray[0].command as string; // Normalize path separators for cross-platform matching (Windows uses backslashes) - const normalizedCommand = command.replace(/\\/g, '/'); + const normalizedCommand = command + .replace(/\\/g, '/') // Windows backslashes + .replace(/\/+/g, '/'); // Collapse multiple slashes return !normalizedCommand.includes('.ccs/hooks/websearch-transformer'); // Remove if CCS hook }); diff --git a/src/utils/websearch/hook-utils.ts b/src/utils/websearch/hook-utils.ts index 85618d64..7a551380 100644 --- a/src/utils/websearch/hook-utils.ts +++ b/src/utils/websearch/hook-utils.ts @@ -20,7 +20,9 @@ export function isCcsWebSearchHook(hook: Record): boolean { if (typeof command !== 'string') return false; // Normalize path separators for cross-platform matching - const normalizedCommand = command.replace(/\\/g, '/'); + const normalizedCommand = command + .replace(/\\/g, '/') // Windows backslashes + .replace(/\/+/g, '/'); // Collapse multiple slashes return normalizedCommand.includes('.ccs/hooks/websearch-transformer'); } diff --git a/src/utils/websearch/profile-hook-injector.ts b/src/utils/websearch/profile-hook-injector.ts index c4fe01de..5a98b00c 100644 --- a/src/utils/websearch/profile-hook-injector.ts +++ b/src/utils/websearch/profile-hook-injector.ts @@ -195,7 +195,9 @@ function updateHookTimeoutIfNeeded( const command = hookArray[0].command; if (typeof command !== 'string') continue; // Normalize path separators for cross-platform matching (Windows uses backslashes) - const normalizedCommand = command.replace(/\\/g, '/'); + const normalizedCommand = command + .replace(/\\/g, '/') // Windows backslashes + .replace(/\/+/g, '/'); // Collapse multiple slashes if (!normalizedCommand.includes('.ccs/hooks/websearch-transformer')) continue; // Found CCS hook - check if needs update diff --git a/tests/unit/utils/websearch/hook-utils.test.ts b/tests/unit/utils/websearch/hook-utils.test.ts index 6bd09c30..a3f7bd3e 100644 --- a/tests/unit/utils/websearch/hook-utils.test.ts +++ b/tests/unit/utils/websearch/hook-utils.test.ts @@ -38,6 +38,18 @@ describe('isCcsWebSearchHook', () => { expect(isCcsWebSearchHook(hook)).toBe(true); }); + test('Returns true for path with double slashes (normalization)', () => { + const hook = { + matcher: 'WebSearch', + hooks: [ + { + command: 'node /home/user//.ccs//hooks/websearch-transformer/index.js', + }, + ], + }; + expect(isCcsWebSearchHook(hook)).toBe(true); + }); + test('Returns false for non-WebSearch matcher', () => { const hook = { matcher: 'SomethingElse',