mirror of
https://github.com/tiennm99/ccs.git
synced 2026-07-15 20:20:09 +00:00
Implements CCS WebSearch Native Infrastructure (Phases 1-3): Phase 1 - Multi-tier MCP Fallback: - Add mcp-manager.ts with ensureMcpWebSearch() for auto-configuration - Support web-search-prime (primary), Brave Search, and Tavily MCPs - Case-insensitive detection of existing web search MCPs - Block-websearch hook for optional native WebSearch blocking Phase 2 - User Configuration: - Add WebSearchConfig interface to unified-config-types.ts - Add getWebSearchConfig() to unified-config-loader.ts - Support configurable webSearchPrimeUrl for security - Add GET/PUT /api/websearch endpoints in routes.ts - Add WebSearch settings UI in settings.tsx dashboard Phase 3 - Documentation & Testing: - Add WebSearch section to README.md - Create comprehensive docs/websearch.md guide - Add 23 unit tests for MCP manager logic Enables web search for gemini, codex, agy, qwen, glm, kimi profiles that cannot access Anthropic's native WebSearch API.
76 lines
2.0 KiB
JavaScript
76 lines
2.0 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* CCS WebSearch Blocking Hook
|
|
*
|
|
* Blocks Claude's native WebSearch tool and redirects to MCP alternative.
|
|
* This is a PreToolUse hook that runs BEFORE the tool is executed.
|
|
*
|
|
* WebSearch is a server-side tool executed by Anthropic's API.
|
|
* Third-party providers (gemini, agy, codex, qwen) don't have access.
|
|
*
|
|
* Usage:
|
|
* Configured in ~/.claude/settings.json:
|
|
* {
|
|
* "hooks": {
|
|
* "PreToolUse": [{
|
|
* "matcher": "WebSearch",
|
|
* "hooks": [{
|
|
* "type": "command",
|
|
* "command": "node ~/.ccs/hooks/block-websearch.cjs",
|
|
* "timeout": 5
|
|
* }]
|
|
* }]
|
|
* }
|
|
* }
|
|
*
|
|
* Exit codes:
|
|
* 0 - Allow tool (pass-through)
|
|
* 2 - Block tool (deny with message)
|
|
*
|
|
* @module hooks/block-websearch
|
|
*/
|
|
|
|
// Read input from stdin
|
|
let input = '';
|
|
process.stdin.setEncoding('utf8');
|
|
process.stdin.on('data', (chunk) => {
|
|
input += chunk;
|
|
});
|
|
process.stdin.on('end', () => {
|
|
try {
|
|
const data = JSON.parse(input);
|
|
|
|
// Only block WebSearch tool
|
|
if (data.tool_name === 'WebSearch') {
|
|
const query = data.tool_input?.query || '';
|
|
|
|
const output = {
|
|
decision: 'block',
|
|
reason: 'WebSearch unavailable with current provider',
|
|
hookSpecificOutput: {
|
|
hookEventName: 'PreToolUse',
|
|
permissionDecision: 'deny',
|
|
permissionDecisionReason: `WebSearch is not available with third-party providers. Use mcp__web-search-prime__webSearchPrime tool instead with the same query: "${query}"`,
|
|
},
|
|
};
|
|
|
|
console.log(JSON.stringify(output));
|
|
process.exit(2); // Exit code 2 = block
|
|
}
|
|
|
|
// Allow all other tools
|
|
process.exit(0);
|
|
} catch (err) {
|
|
// Don't block on parse errors - allow tool to proceed
|
|
if (process.env.CCS_DEBUG) {
|
|
console.error('[CCS Hook] Parse error:', err.message);
|
|
}
|
|
process.exit(0);
|
|
}
|
|
});
|
|
|
|
// Handle stdin not being available
|
|
process.stdin.on('error', () => {
|
|
process.exit(0);
|
|
});
|