diff --git a/src/utils/websearch/claude-tool-args.ts b/src/utils/websearch/claude-tool-args.ts index 8e9b7584..62de05ce 100644 --- a/src/utils/websearch/claude-tool-args.ts +++ b/src/utils/websearch/claude-tool-args.ts @@ -12,6 +12,14 @@ function parseToolValue(rawValue: string): string[] { .filter((value) => value.length > 0); } +function mergeToolValues(rawValues: string[], toolName: string): string { + const merged = rawValues.flatMap(parseToolValue); + if (!merged.includes(toolName)) { + merged.push(toolName); + } + return merged.join(','); +} + function hasToolInFlag(args: string[], flag: string, toolName: string): boolean { for (let index = 0; index < args.length; index += 1) { const arg = args[index]; @@ -47,5 +55,34 @@ export function appendThirdPartyWebSearchToolArgs(args: string[]): string[] { return args; } + for (let index = 0; index < args.length; index += 1) { + const arg = args[index]; + + if (arg === DISALLOWED_TOOLS_FLAG) { + let cursor = index + 1; + const rawValues: string[] = []; + + while (cursor < args.length && !args[cursor].startsWith('--')) { + rawValues.push(args[cursor]); + cursor += 1; + } + + return [ + ...args.slice(0, index + 1), + mergeToolValues(rawValues, NATIVE_WEBSEARCH_TOOL), + ...args.slice(cursor), + ]; + } + + if (arg.startsWith(`${DISALLOWED_TOOLS_FLAG}=`)) { + const rawValue = arg.slice(DISALLOWED_TOOLS_FLAG.length + 1); + return [ + ...args.slice(0, index), + `${DISALLOWED_TOOLS_FLAG}=${mergeToolValues([rawValue], NATIVE_WEBSEARCH_TOOL)}`, + ...args.slice(index + 1), + ]; + } + } + return [...args, DISALLOWED_TOOLS_FLAG, NATIVE_WEBSEARCH_TOOL]; } diff --git a/tests/unit/utils/websearch/claude-tool-args.test.ts b/tests/unit/utils/websearch/claude-tool-args.test.ts index e96d4de0..6eb2367c 100644 --- a/tests/unit/utils/websearch/claude-tool-args.test.ts +++ b/tests/unit/utils/websearch/claude-tool-args.test.ts @@ -21,4 +21,19 @@ describe('appendThirdPartyWebSearchToolArgs', () => { ['smoke', '--disallowedTools=Read,WebSearch'] ); }); + + it('merges WebSearch into an existing space-separated disallowed tool flag', () => { + expect(appendThirdPartyWebSearchToolArgs(['smoke', '--disallowedTools', 'Read'])).toEqual([ + 'smoke', + '--disallowedTools', + 'Read,WebSearch', + ]); + }); + + it('merges WebSearch into an existing equals-form disallowed tool flag', () => { + expect(appendThirdPartyWebSearchToolArgs(['smoke', '--disallowedTools=Read'])).toEqual([ + 'smoke', + '--disallowedTools=Read,WebSearch', + ]); + }); });