mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-13 02:41:50 +08:00
Add tool strategy documentation with triggering mechanisms and text processing references
- Introduced auto and manual triggering mechanisms for Exa. - Added quick reference guides for sed and awk text processing. - Established a fallback strategy for handling edit failures.
This commit is contained in:
@@ -157,22 +157,36 @@ function renderReviewContent(review) {
|
||||
// Lite Context Tab Rendering
|
||||
// ==========================================
|
||||
|
||||
function renderLiteContextContent(context, session) {
|
||||
function renderLiteContextContent(context, explorations, session) {
|
||||
const plan = session.plan || {};
|
||||
let sections = [];
|
||||
|
||||
// Render explorations if available (from exploration-*.json files)
|
||||
if (explorations && explorations.manifest) {
|
||||
sections.push(renderExplorationContext(explorations));
|
||||
}
|
||||
|
||||
// If we have context from context-package.json
|
||||
if (context) {
|
||||
return `
|
||||
<div class="context-tab-content">
|
||||
<pre class="json-content">${escapeHtml(JSON.stringify(context, null, 2))}</pre>
|
||||
sections.push(`
|
||||
<div class="context-package-section">
|
||||
<div class="collapsible-section">
|
||||
<div class="collapsible-header">
|
||||
<span class="collapse-icon">▶</span>
|
||||
<span class="section-label">Context Package</span>
|
||||
</div>
|
||||
<div class="collapsible-content collapsed">
|
||||
<pre class="json-content">${escapeHtml(JSON.stringify(context, null, 2))}</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
`);
|
||||
}
|
||||
|
||||
// Fallback: show context from plan
|
||||
if (plan.focus_paths?.length || plan.summary) {
|
||||
return `
|
||||
<div class="context-tab-content">
|
||||
sections.push(`
|
||||
<div class="plan-context-section">
|
||||
${plan.summary ? `
|
||||
<div class="context-section">
|
||||
<h4>Summary</h4>
|
||||
@@ -188,18 +202,24 @@ function renderLiteContextContent(context, session) {
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
`;
|
||||
`);
|
||||
}
|
||||
|
||||
// If we have any sections, wrap them
|
||||
if (sections.length > 0) {
|
||||
return `<div class="context-tab-content">${sections.join('')}</div>`;
|
||||
}
|
||||
|
||||
return `
|
||||
<div class="tab-empty-state">
|
||||
<div class="empty-icon">📦</div>
|
||||
<div class="empty-title">No Context Data</div>
|
||||
<div class="empty-text">No context-package.json found for this session.</div>
|
||||
<div class="empty-text">No context-package.json or exploration files found for this session.</div>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
// ==========================================
|
||||
// Exploration Context Rendering
|
||||
// ==========================================
|
||||
@@ -228,24 +248,28 @@ function renderExplorationContext(explorations) {
|
||||
// Render each exploration angle as collapsible section
|
||||
const explorationOrder = ['architecture', 'dependencies', 'patterns', 'integration-points'];
|
||||
const explorationTitles = {
|
||||
'architecture': 'Architecture',
|
||||
'dependencies': 'Dependencies',
|
||||
'patterns': 'Patterns',
|
||||
'integration-points': 'Integration Points'
|
||||
'architecture': '🏗️ Architecture',
|
||||
'dependencies': '📦 Dependencies',
|
||||
'patterns': '🔄 Patterns',
|
||||
'integration-points': '🔌 Integration Points'
|
||||
};
|
||||
|
||||
for (const angle of explorationOrder) {
|
||||
const expData = data[angle];
|
||||
if (!expData) continue;
|
||||
if (!expData) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const angleContent = renderExplorationAngle(angle, expData);
|
||||
|
||||
sections.push(`
|
||||
<div class="exploration-section collapsible-section">
|
||||
<div class="collapsible-header" onclick="toggleSection(this)">
|
||||
<div class="collapsible-header">
|
||||
<span class="collapse-icon">▶</span>
|
||||
<span class="section-label">${explorationTitles[angle] || angle}</span>
|
||||
</div>
|
||||
<div class="collapsible-content collapsed">
|
||||
${renderExplorationAngle(angle, expData)}
|
||||
${angleContent}
|
||||
</div>
|
||||
</div>
|
||||
`);
|
||||
@@ -276,8 +300,8 @@ function renderExplorationAngle(angle, data) {
|
||||
${data.relevant_files.slice(0, 10).map(f => `
|
||||
<div class="file-item-exp">
|
||||
<div class="file-path"><code>${escapeHtml(f.path || '')}</code></div>
|
||||
<div class="file-relevance">Relevance: ${(f.relevance * 100).toFixed(0)}%</div>
|
||||
${f.rationale ? `<div class="file-rationale">${escapeHtml(f.rationale.substring(0, 200))}...</div>` : ''}
|
||||
<div class="file-relevance">Relevance: ${f.relevance ? (f.relevance * 100).toFixed(0) : 0}%</div>
|
||||
${f.rationale ? `<div class="file-rationale">${escapeHtml((f.rationale || "").substring(0, 200))}...</div>` : ''}
|
||||
</div>
|
||||
`).join('')}
|
||||
${data.relevant_files.length > 10 ? `<div class="more-files">... and ${data.relevant_files.length - 10} more files</div>` : ''}
|
||||
@@ -349,5 +373,6 @@ function renderExplorationAngle(angle, data) {
|
||||
`);
|
||||
}
|
||||
|
||||
return content.join('') || '<p>No data available</p>';
|
||||
const result = content.join('') || '<p>No data available</p>';
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -132,3 +132,22 @@ function toggleSection(header) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize collapsible sections within a container
|
||||
* @param {HTMLElement} container - Container element to search within
|
||||
*/
|
||||
function initCollapsibleSections(container) {
|
||||
setTimeout(() => {
|
||||
const headers = container.querySelectorAll('.collapsible-header');
|
||||
headers.forEach(header => {
|
||||
if (!header._clickBound) {
|
||||
header._clickBound = true;
|
||||
header.addEventListener('click', function(e) {
|
||||
e.stopPropagation();
|
||||
toggleSection(this);
|
||||
});
|
||||
}
|
||||
});
|
||||
}, 100);
|
||||
}
|
||||
|
||||
@@ -347,17 +347,14 @@ async function loadAndRenderLiteContextTab(session, contentArea) {
|
||||
const data = await response.json();
|
||||
contentArea.innerHTML = renderLiteContextContent(data.context, data.explorations, session);
|
||||
|
||||
// Re-initialize collapsible sections for explorations
|
||||
setTimeout(() => {
|
||||
document.querySelectorAll('.collapsible-header').forEach(header => {
|
||||
header.addEventListener('click', () => toggleSection(header));
|
||||
});
|
||||
}, 50);
|
||||
// Re-initialize collapsible sections for explorations (scoped to contentArea)
|
||||
initCollapsibleSections(contentArea);
|
||||
return;
|
||||
}
|
||||
}
|
||||
// Fallback: show plan context if available
|
||||
contentArea.innerHTML = renderLiteContextContent(null, null, session);
|
||||
initCollapsibleSections(contentArea);
|
||||
} catch (err) {
|
||||
contentArea.innerHTML = `<div class="tab-error">Failed to load context: ${err.message}</div>`;
|
||||
}
|
||||
|
||||
@@ -81,36 +81,70 @@ async function renderMcpManager() {
|
||||
`}
|
||||
</div>
|
||||
|
||||
<!-- All Projects Overview -->
|
||||
<!-- All Projects MCP Overview Table -->
|
||||
<div class="mcp-section mt-6">
|
||||
<div class="flex items-center justify-between mb-4">
|
||||
<h3 class="text-lg font-semibold text-foreground">All Projects</h3>
|
||||
<h3 class="text-lg font-semibold text-foreground">All Projects MCP Overview</h3>
|
||||
<span class="text-sm text-muted-foreground">${Object.keys(mcpAllProjects).length} projects</span>
|
||||
</div>
|
||||
|
||||
<div class="mcp-projects-list bg-card border border-border rounded-lg overflow-hidden">
|
||||
${Object.entries(mcpAllProjects).map(([path, config]) => {
|
||||
const servers = config.mcpServers || {};
|
||||
const serverCount = Object.keys(servers).length;
|
||||
const isCurrentProject = path === currentPath;
|
||||
return `
|
||||
<div class="mcp-project-item flex items-center justify-between px-4 py-3 border-b border-border last:border-b-0 hover:bg-hover cursor-pointer ${isCurrentProject ? 'bg-primary-light' : ''}"
|
||||
onclick="switchToProject('${escapeHtml(path)}')"
|
||||
data-project-path="${escapeHtml(path)}">
|
||||
<div class="flex items-center gap-3 min-w-0">
|
||||
<span class="text-lg">${isCurrentProject ? '📍' : '📁'}</span>
|
||||
<div class="min-w-0">
|
||||
<div class="font-medium text-foreground truncate" title="${escapeHtml(path)}">${escapeHtml(path.split('\\').pop() || path)}</div>
|
||||
<div class="text-xs text-muted-foreground truncate">${escapeHtml(path)}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex items-center gap-2 shrink-0">
|
||||
<span class="badge px-2 py-0.5 text-xs font-semibold rounded-full ${serverCount > 0 ? 'bg-success-light text-success' : 'bg-hover text-muted-foreground'}">${serverCount} MCP</span>
|
||||
${isCurrentProject ? '<span class="text-xs text-primary font-medium">Current</span>' : ''}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
}).join('')}
|
||||
<div class="mcp-projects-table bg-card border border-border rounded-lg overflow-hidden">
|
||||
<table class="w-full">
|
||||
<thead class="bg-muted/50">
|
||||
<tr>
|
||||
<th class="text-left px-4 py-3 text-sm font-semibold text-foreground border-b border-border">Project</th>
|
||||
<th class="text-left px-4 py-3 text-sm font-semibold text-foreground border-b border-border">MCP Servers</th>
|
||||
<th class="text-center px-4 py-3 text-sm font-semibold text-foreground border-b border-border w-24">Status</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
${Object.entries(mcpAllProjects).map(([path, config]) => {
|
||||
const servers = config.mcpServers || {};
|
||||
const projectDisabled = config.disabledMcpServers || [];
|
||||
const serverNames = Object.keys(servers);
|
||||
const isCurrentProject = path === currentPath;
|
||||
const enabledCount = serverNames.filter(s => !projectDisabled.includes(s)).length;
|
||||
|
||||
return `
|
||||
<tr class="border-b border-border last:border-b-0 ${isCurrentProject ? 'bg-primary/5' : 'hover:bg-hover/50'}">
|
||||
<td class="px-4 py-3">
|
||||
<div class="flex items-center gap-2 min-w-0">
|
||||
<span class="text-base shrink-0">${isCurrentProject ? '📍' : '📁'}</span>
|
||||
<div class="min-w-0">
|
||||
<div class="font-medium text-foreground truncate text-sm" title="${escapeHtml(path)}">
|
||||
${escapeHtml(path.split('\\').pop() || path)}
|
||||
${isCurrentProject ? '<span class="ml-2 text-xs text-primary font-medium">(Current)</span>' : ''}
|
||||
</div>
|
||||
<div class="text-xs text-muted-foreground truncate">${escapeHtml(path)}</div>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3">
|
||||
<div class="flex flex-wrap gap-1.5">
|
||||
${serverNames.length === 0
|
||||
? '<span class="text-xs text-muted-foreground italic">No MCP servers</span>'
|
||||
: serverNames.map(serverName => {
|
||||
const isEnabled = !projectDisabled.includes(serverName);
|
||||
return `
|
||||
<span class="inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium rounded-full ${isEnabled ? 'bg-success-light text-success' : 'bg-hover text-muted-foreground'}">
|
||||
<span class="w-1.5 h-1.5 rounded-full ${isEnabled ? 'bg-success' : 'bg-muted-foreground'}"></span>
|
||||
${escapeHtml(serverName)}
|
||||
</span>
|
||||
`;
|
||||
}).join('')
|
||||
}
|
||||
</div>
|
||||
</td>
|
||||
<td class="px-4 py-3 text-center">
|
||||
<span class="inline-flex items-center px-2 py-1 text-xs font-semibold rounded-full ${serverNames.length > 0 ? 'bg-success-light text-success' : 'bg-hover text-muted-foreground'}">
|
||||
${enabledCount}/${serverNames.length}
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
`;
|
||||
}).join('')}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -235,8 +269,3 @@ function attachMcpEventListeners() {
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function switchToProject(path) {
|
||||
// Use existing path selection mechanism
|
||||
selectPath(path.replace(/\\\\/g, '\\'));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user