Skip to content

Commit bfcc30b

Browse files
GeneAIclaude
authored andcommitted
feat(vscode): Enhanced sync-claude webview with rich formatting
- Clickable file links to .claude/rules/empathy/*.md files - Pattern counts by category in a table - Sample patterns preview from debugging.md - Quick actions section with folder link - Raw output in collapsible details section 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent e075f2d commit bfcc30b

File tree

1 file changed

+81
-1
lines changed

1 file changed

+81
-1
lines changed

vscode-extension/src/panels/EmpathyDashboardPanel.ts

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1395,6 +1395,7 @@ export class EmpathyDashboardProvider implements vscode.WebviewViewProvider {
13951395

13961396
const displayName = workflowNames[workflowName] || workflowName;
13971397
const timestamp = new Date().toLocaleString();
1398+
const workspaceFolder = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || '';
13981399

13991400
// Format the report as markdown
14001401
let content = `# ${displayName} Report\n\n`;
@@ -1404,8 +1405,12 @@ export class EmpathyDashboardProvider implements vscode.WebviewViewProvider {
14041405
}
14051406
content += `\n---\n\n`;
14061407

1408+
// Special formatting for sync-claude output
1409+
if (workflowName === 'sync-claude') {
1410+
content = this._formatSyncClaudeReport(output, timestamp, workspaceFolder);
1411+
}
14071412
// Try to parse as JSON for structured formatting, otherwise use raw output
1408-
try {
1413+
else try {
14091414
const parsed = JSON.parse(output);
14101415
content += this._formatJsonReport(parsed);
14111416
} catch {
@@ -1504,6 +1509,81 @@ export class EmpathyDashboardProvider implements vscode.WebviewViewProvider {
15041509
return content;
15051510
}
15061511

1512+
/**
1513+
* Format sync-claude output with enhanced display:
1514+
* - Clickable file links
1515+
* - Pattern counts by category
1516+
* - Sample patterns preview
1517+
*/
1518+
private _formatSyncClaudeReport(output: string, timestamp: string, workspaceFolder: string): string {
1519+
let content = `# 🔄 Sync to Claude Code\n\n`;
1520+
content += `**Generated:** ${timestamp}\n\n`;
1521+
1522+
// Parse categories from output (format: "✓ category: N patterns → path")
1523+
const categoryRegex = /\s+(\w+):\s+(\d+)\s+patterns\s+\s+(.+\.md)/g;
1524+
const categories: Array<{ name: string; count: number; file: string }> = [];
1525+
let match;
1526+
while ((match = categoryRegex.exec(output)) !== null) {
1527+
categories.push({ name: match[1], count: parseInt(match[2]), file: match[3] });
1528+
}
1529+
1530+
// Extract total from output
1531+
const totalMatch = output.match(/Total:\s+(\d+)\s+patterns/);
1532+
const totalPatterns = totalMatch ? parseInt(totalMatch[1]) : categories.reduce((sum, c) => sum + c.count, 0);
1533+
1534+
// Summary section
1535+
content += `## ✅ Summary\n\n`;
1536+
content += `**${totalPatterns} patterns** synced to Claude Code rules.\n\n`;
1537+
1538+
// Categories table with clickable links
1539+
if (categories.length > 0) {
1540+
content += `## 📁 Pattern Categories\n\n`;
1541+
content += `| Category | Patterns | File |\n`;
1542+
content += `|----------|----------|------|\n`;
1543+
for (const cat of categories) {
1544+
const fileName = cat.file.split('/').pop() || cat.file;
1545+
content += `| ${cat.name} | ${cat.count} | [${fileName}](${cat.file}) |\n`;
1546+
}
1547+
content += `\n`;
1548+
}
1549+
1550+
// Load and show sample patterns
1551+
content += `## 🔍 Sample Patterns\n\n`;
1552+
try {
1553+
const debuggingPath = path.join(workspaceFolder, '.claude', 'rules', 'empathy', 'debugging.md');
1554+
if (fs.existsSync(debuggingPath)) {
1555+
const debugContent = fs.readFileSync(debuggingPath, 'utf-8');
1556+
// Extract first 3 patterns (look for "### " headers after "## Bug Fix Patterns")
1557+
const patternRegex = /###\s+(\w+)\n-\s+\*\*Root cause\*\*:\s+(.+)\n/g;
1558+
const patterns: string[] = [];
1559+
let patMatch;
1560+
while ((patMatch = patternRegex.exec(debugContent)) !== null && patterns.length < 3) {
1561+
patterns.push(`- **${patMatch[1]}**: ${patMatch[2]}`);
1562+
}
1563+
if (patterns.length > 0) {
1564+
content += `Recent debugging patterns:\n\n${patterns.join('\n')}\n\n`;
1565+
} else {
1566+
content += `_No sample patterns available._\n\n`;
1567+
}
1568+
} else {
1569+
content += `_Pattern files will be available after sync._\n\n`;
1570+
}
1571+
} catch {
1572+
content += `_Could not load sample patterns._\n\n`;
1573+
}
1574+
1575+
// Quick actions section
1576+
content += `## ⚡ Quick Actions\n\n`;
1577+
content += `- 📂 [Open Rules Folder](.claude/rules/empathy/)\n`;
1578+
content += `- 🔄 Run \`empathy sync-claude\` to re-sync\n`;
1579+
content += `- 📖 Patterns are now available to Claude Code\n\n`;
1580+
1581+
// Raw output (collapsed)
1582+
content += `<details>\n<summary>📋 Raw Output</summary>\n\n\`\`\`\n${output}\n\`\`\`\n</details>\n`;
1583+
1584+
return content;
1585+
}
1586+
15071587
/**
15081588
* Save security audit findings to file and trigger diagnostics refresh
15091589
*/

0 commit comments

Comments
 (0)