mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-11 02:33:51 +08:00
Add comprehensive tests for query parsing and Reciprocal Rank Fusion
- Implemented tests for the QueryParser class, covering various identifier splitting methods (CamelCase, snake_case, kebab-case), OR expansion, and FTS5 operator preservation. - Added parameterized tests to validate expected token outputs for different query formats. - Created edge case tests to ensure robustness against unusual input scenarios. - Developed tests for the Reciprocal Rank Fusion (RRF) algorithm, including score computation, weight handling, and result ranking across multiple sources. - Included tests for normalization of BM25 scores and tagging search results with source metadata.
This commit is contained in:
@@ -1068,3 +1068,55 @@ async function updateCcwToolsMcp(scope = 'workspace') {
|
||||
showRefreshToast(`Failed to update CCW Tools MCP: ${err.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
// ========================================
|
||||
// CCW Tools MCP for Codex
|
||||
// ========================================
|
||||
|
||||
// Get selected tools from Codex checkboxes
|
||||
function getSelectedCcwToolsCodex() {
|
||||
const checkboxes = document.querySelectorAll('.ccw-tool-checkbox-codex:checked');
|
||||
return Array.from(checkboxes).map(cb => cb.dataset.tool);
|
||||
}
|
||||
|
||||
// Select tools by category for Codex
|
||||
function selectCcwToolsCodex(type) {
|
||||
const checkboxes = document.querySelectorAll('.ccw-tool-checkbox-codex');
|
||||
const coreTools = ['write_file', 'edit_file', 'codex_lens', 'smart_search'];
|
||||
|
||||
checkboxes.forEach(cb => {
|
||||
if (type === 'all') {
|
||||
cb.checked = true;
|
||||
} else if (type === 'none') {
|
||||
cb.checked = false;
|
||||
} else if (type === 'core') {
|
||||
cb.checked = coreTools.includes(cb.dataset.tool);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Install/Update CCW Tools MCP to Codex
|
||||
async function installCcwToolsMcpToCodex() {
|
||||
const selectedTools = getSelectedCcwToolsCodex();
|
||||
|
||||
if (selectedTools.length === 0) {
|
||||
showRefreshToast('Please select at least one tool', 'warning');
|
||||
return;
|
||||
}
|
||||
|
||||
const ccwToolsConfig = buildCcwToolsConfig(selectedTools);
|
||||
|
||||
try {
|
||||
const isUpdate = codexMcpServers && codexMcpServers['ccw-tools'];
|
||||
const actionLabel = isUpdate ? 'Updating' : 'Installing';
|
||||
showRefreshToast(`${actionLabel} CCW Tools MCP to Codex...`, 'info');
|
||||
|
||||
await addCodexMcpServer('ccw-tools', ccwToolsConfig);
|
||||
|
||||
const resultLabel = isUpdate ? 'updated in' : 'installed to';
|
||||
showRefreshToast(`CCW Tools ${resultLabel} Codex (${selectedTools.length} tools)`, 'success');
|
||||
} catch (err) {
|
||||
console.error('Failed to install CCW Tools MCP to Codex:', err);
|
||||
showRefreshToast(`Failed to install CCW Tools MCP to Codex: ${err.message}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ const CCW_MCP_TOOLS = [
|
||||
{ name: 'cli_executor', desc: 'Gemini/Qwen/Codex CLI', core: false },
|
||||
];
|
||||
|
||||
// Get currently enabled tools from installed config
|
||||
// Get currently enabled tools from installed config (Claude)
|
||||
function getCcwEnabledTools() {
|
||||
const currentPath = projectPath; // Keep original format (forward slash)
|
||||
const projectData = mcpAllProjects[currentPath] || {};
|
||||
@@ -28,6 +28,18 @@ function getCcwEnabledTools() {
|
||||
return CCW_MCP_TOOLS.filter(t => t.core).map(t => t.name);
|
||||
}
|
||||
|
||||
// Get currently enabled tools from Codex config
|
||||
function getCcwEnabledToolsCodex() {
|
||||
const ccwConfig = codexMcpServers?.['ccw-tools'];
|
||||
if (ccwConfig?.env?.CCW_ENABLED_TOOLS) {
|
||||
const val = ccwConfig.env.CCW_ENABLED_TOOLS;
|
||||
if (val.toLowerCase() === 'all') return CCW_MCP_TOOLS.map(t => t.name);
|
||||
return val.split(',').map(t => t.trim());
|
||||
}
|
||||
// Default to core tools if not installed
|
||||
return CCW_MCP_TOOLS.filter(t => t.core).map(t => t.name);
|
||||
}
|
||||
|
||||
async function renderMcpManager() {
|
||||
const container = document.getElementById('mainContent');
|
||||
if (!container) return;
|
||||
@@ -120,6 +132,7 @@ async function renderMcpManager() {
|
||||
// Check if CCW Tools is already installed
|
||||
const isCcwToolsInstalled = currentProjectServerNames.includes("ccw-tools");
|
||||
const enabledTools = getCcwEnabledTools();
|
||||
const enabledToolsCodex = getCcwEnabledToolsCodex();
|
||||
|
||||
// Prepare Codex servers data
|
||||
const codexServerEntries = Object.entries(codexMcpServers || {});
|
||||
@@ -157,6 +170,60 @@ async function renderMcpManager() {
|
||||
</div>
|
||||
|
||||
${currentCliMode === 'codex' ? `
|
||||
<!-- CCW Tools MCP Server Card (Codex mode) -->
|
||||
<div class="mcp-section mb-6">
|
||||
<div class="ccw-tools-card bg-gradient-to-br from-orange-500/10 to-orange-500/5 border-2 ${codexMcpServers && codexMcpServers['ccw-tools'] ? 'border-success' : 'border-orange-500/30'} rounded-lg p-6 hover:shadow-lg transition-all">
|
||||
<div class="flex items-start justify-between gap-4">
|
||||
<div class="flex items-start gap-4 flex-1">
|
||||
<div class="shrink-0 w-12 h-12 bg-orange-500 rounded-lg flex items-center justify-center">
|
||||
<i data-lucide="wrench" class="w-6 h-6 text-white"></i>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<h3 class="text-lg font-bold text-foreground">CCW Tools MCP</h3>
|
||||
<span class="text-xs px-2 py-0.5 bg-orange-100 text-orange-700 dark:bg-orange-900/30 dark:text-orange-300 rounded-full">Codex</span>
|
||||
${codexMcpServers && codexMcpServers['ccw-tools'] ? `
|
||||
<span class="inline-flex items-center gap-1 px-2 py-0.5 text-xs font-semibold rounded-full bg-success-light text-success">
|
||||
<i data-lucide="check" class="w-3 h-3"></i>
|
||||
${enabledToolsCodex.length} tools
|
||||
</span>
|
||||
` : `
|
||||
<span class="inline-flex items-center gap-1 px-2 py-0.5 text-xs font-semibold rounded-full bg-orange-500/20 text-orange-600 dark:text-orange-400">
|
||||
<i data-lucide="package" class="w-3 h-3"></i>
|
||||
${t('mcp.available')}
|
||||
</span>
|
||||
`}
|
||||
</div>
|
||||
<p class="text-sm text-muted-foreground mb-3">${t('mcp.ccwToolsDesc')}</p>
|
||||
<!-- Tool Selection Grid for Codex -->
|
||||
<div class="grid grid-cols-3 sm:grid-cols-5 gap-2 mb-3">
|
||||
${CCW_MCP_TOOLS.map(tool => `
|
||||
<label class="flex items-center gap-1.5 text-xs cursor-pointer hover:bg-muted/50 rounded px-1.5 py-1 transition-colors">
|
||||
<input type="checkbox" class="ccw-tool-checkbox-codex w-3 h-3"
|
||||
data-tool="${tool.name}"
|
||||
${enabledToolsCodex.includes(tool.name) ? 'checked' : ''}>
|
||||
<span class="${tool.core ? 'font-medium' : 'text-muted-foreground'}">${tool.desc}</span>
|
||||
</label>
|
||||
`).join('')}
|
||||
</div>
|
||||
<div class="flex items-center gap-3 text-xs">
|
||||
<button class="text-orange-500 hover:underline" onclick="selectCcwToolsCodex('core')">Core only</button>
|
||||
<button class="text-orange-500 hover:underline" onclick="selectCcwToolsCodex('all')">All</button>
|
||||
<button class="text-muted-foreground hover:underline" onclick="selectCcwToolsCodex('none')">None</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="shrink-0">
|
||||
<button class="px-4 py-2 text-sm bg-orange-500 text-white rounded-lg hover:opacity-90 transition-opacity flex items-center gap-1"
|
||||
onclick="installCcwToolsMcpToCodex()">
|
||||
<i data-lucide="download" class="w-4 h-4"></i>
|
||||
${codexMcpServers && codexMcpServers['ccw-tools'] ? t('mcp.update') : t('mcp.install')}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Codex MCP Servers Section -->
|
||||
<div class="mcp-section mb-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
|
||||
Reference in New Issue
Block a user