mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-03-01 09:43:26 +08:00
feat: add experimental support for AST parsing and static graph indexing
- Introduced CLI options for using AST grep parsers and enabling static graph relationships during indexing. - Updated configuration management to load new settings for AST parsing and static graph types. - Enhanced AST grep processor to handle imports with aliases and improve relationship tracking. - Modified TreeSitter parsers to support synthetic module scopes for better static graph persistence. - Implemented global relationship updates in the incremental indexer for static graph expansion. - Added new ArtifactTag and FloatingFileBrowser components to the frontend for improved terminal dashboard functionality. - Created utility functions for detecting CCW artifacts in terminal output with associated tests.
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
// Manage MCP servers (Model Context Protocol) with tabbed interface
|
||||
// Supports Templates, Servers, and Cross-CLI tabs
|
||||
|
||||
import { useState } from 'react';
|
||||
import { useState, useMemo } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import {
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
ChevronDown,
|
||||
ChevronUp,
|
||||
BookmarkPlus,
|
||||
AlertTriangle,
|
||||
} from 'lucide-react';
|
||||
import { Card } from '@/components/ui/Card';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
@@ -38,16 +39,20 @@ import { AllProjectsTable } from '@/components/mcp/AllProjectsTable';
|
||||
import { OtherProjectsSection } from '@/components/mcp/OtherProjectsSection';
|
||||
import { TabsNavigation } from '@/components/ui/TabsNavigation';
|
||||
import { useMcpServers, useMcpServerMutations, useNotifications } from '@/hooks';
|
||||
import { useWorkflowStore, selectProjectPath } from '@/stores/workflowStore';
|
||||
import {
|
||||
fetchCodexMcpServers,
|
||||
fetchCcwMcpConfig,
|
||||
fetchCcwMcpConfigForCodex,
|
||||
updateCcwConfig,
|
||||
updateCcwConfigForCodex,
|
||||
installCcwMcp,
|
||||
uninstallCcwMcpFromScope,
|
||||
codexRemoveServer,
|
||||
codexToggleServer,
|
||||
saveMcpTemplate,
|
||||
type McpServer,
|
||||
type McpServerConflict,
|
||||
type CcwMcpConfig,
|
||||
} from '@/lib/api';
|
||||
import { cn } from '@/lib/utils';
|
||||
@@ -62,9 +67,10 @@ interface McpServerCardProps {
|
||||
onEdit: (server: McpServer) => void;
|
||||
onDelete: (server: McpServer) => void;
|
||||
onSaveAsTemplate: (server: McpServer) => void;
|
||||
conflictInfo?: McpServerConflict;
|
||||
}
|
||||
|
||||
function McpServerCard({ server, isExpanded, onToggleExpand, onToggle, onEdit, onDelete, onSaveAsTemplate }: McpServerCardProps) {
|
||||
function McpServerCard({ server, isExpanded, onToggleExpand, onToggle, onEdit, onDelete, onSaveAsTemplate, conflictInfo }: McpServerCardProps) {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
@@ -97,6 +103,12 @@ function McpServerCard({ server, isExpanded, onToggleExpand, onToggle, onEdit, o
|
||||
<><Folder className="w-3 h-3 mr-1" />{formatMessage({ id: 'mcp.scope.project' })}</>
|
||||
)}
|
||||
</Badge>
|
||||
{conflictInfo && (
|
||||
<Badge variant="outline" className="text-xs text-orange-500 border-orange-300">
|
||||
<AlertTriangle className="w-3 h-3 mr-1" />
|
||||
{formatMessage({ id: 'mcp.conflict.badge' })}
|
||||
</Badge>
|
||||
)}
|
||||
{server.enabled && (
|
||||
<Badge variant="outline" className="text-xs text-green-600">
|
||||
{formatMessage({ id: 'mcp.status.enabled' })}
|
||||
@@ -205,6 +217,22 @@ function McpServerCard({ server, isExpanded, onToggleExpand, onToggle, onEdit, o
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Conflict warning panel */}
|
||||
{conflictInfo && (
|
||||
<div className="p-3 bg-orange-50 dark:bg-orange-950/30 border border-orange-200 dark:border-orange-800 rounded-lg space-y-1">
|
||||
<div className="flex items-center gap-2 text-orange-700 dark:text-orange-400">
|
||||
<AlertTriangle className="w-4 h-4" />
|
||||
<span className="text-sm font-medium">{formatMessage({ id: 'mcp.conflict.title' })}</span>
|
||||
</div>
|
||||
<p className="text-xs text-orange-600 dark:text-orange-400/80">
|
||||
{formatMessage({ id: 'mcp.conflict.description' }, { scope: formatMessage({ id: `mcp.scope.${conflictInfo.effectiveScope}` }) })}
|
||||
</p>
|
||||
<p className="text-xs text-orange-600 dark:text-orange-400/80">
|
||||
{formatMessage({ id: 'mcp.conflict.resolution' })}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</Card>
|
||||
@@ -233,6 +261,7 @@ export function McpManagerPage() {
|
||||
servers,
|
||||
projectServers,
|
||||
globalServers,
|
||||
conflicts,
|
||||
totalCount,
|
||||
enabledCount,
|
||||
isLoading,
|
||||
@@ -350,6 +379,7 @@ export function McpManagerPage() {
|
||||
projectRoot: undefined,
|
||||
allowedDirs: undefined,
|
||||
enableSandbox: undefined,
|
||||
installedScopes: [] as ('global' | 'project')[],
|
||||
};
|
||||
|
||||
const handleToggleCcwTool = async (tool: string, enabled: boolean) => {
|
||||
@@ -401,13 +431,43 @@ export function McpManagerPage() {
|
||||
ccwMcpQuery.refetch();
|
||||
};
|
||||
|
||||
const projectPath = useWorkflowStore(selectProjectPath);
|
||||
|
||||
// Build conflict map for quick lookup
|
||||
const conflictMap = useMemo(() => {
|
||||
const map = new Map<string, McpServerConflict>();
|
||||
for (const c of conflicts) map.set(c.name, c);
|
||||
return map;
|
||||
}, [conflicts]);
|
||||
|
||||
// CCW scope-specific handlers
|
||||
const handleCcwInstallToScope = async (scope: 'global' | 'project') => {
|
||||
try {
|
||||
await installCcwMcp(scope, scope === 'project' ? projectPath ?? undefined : undefined);
|
||||
ccwMcpQuery.refetch();
|
||||
} catch (error) {
|
||||
console.error('Failed to install CCW MCP to scope:', error);
|
||||
}
|
||||
};
|
||||
|
||||
const handleCcwUninstallFromScope = async (scope: 'global' | 'project') => {
|
||||
try {
|
||||
await uninstallCcwMcpFromScope(scope, scope === 'project' ? projectPath ?? undefined : undefined);
|
||||
ccwMcpQuery.refetch();
|
||||
queryClient.invalidateQueries({ queryKey: ['mcpServers'] });
|
||||
} catch (error) {
|
||||
console.error('Failed to uninstall CCW MCP from scope:', error);
|
||||
}
|
||||
};
|
||||
|
||||
// CCW MCP handlers for Codex mode
|
||||
const ccwCodexConfig = ccwMcpCodexQuery.data ?? {
|
||||
isInstalled: false,
|
||||
enabledTools: [],
|
||||
enabledTools: [] as string[],
|
||||
projectRoot: undefined,
|
||||
allowedDirs: undefined,
|
||||
enableSandbox: undefined,
|
||||
installedScopes: [] as ('global' | 'project')[],
|
||||
};
|
||||
|
||||
const handleToggleCcwToolCodex = async (tool: string, enabled: boolean) => {
|
||||
@@ -725,6 +785,9 @@ export function McpManagerPage() {
|
||||
onToggleTool={handleToggleCcwTool}
|
||||
onUpdateConfig={handleUpdateCcwConfig}
|
||||
onInstall={handleCcwInstall}
|
||||
installedScopes={ccwConfig.installedScopes}
|
||||
onInstallToScope={handleCcwInstallToScope}
|
||||
onUninstallScope={handleCcwUninstallFromScope}
|
||||
/>
|
||||
)}
|
||||
{cliMode === 'codex' && (
|
||||
@@ -761,7 +824,7 @@ export function McpManagerPage() {
|
||||
{currentServers.map((server) => (
|
||||
cliMode === 'codex' ? (
|
||||
<CodexMcpEditableCard
|
||||
key={server.name}
|
||||
key={`${server.name}-${server.scope}`}
|
||||
server={server as McpServer}
|
||||
enabled={server.enabled}
|
||||
isExpanded={currentExpanded.has(server.name)}
|
||||
@@ -772,14 +835,15 @@ export function McpManagerPage() {
|
||||
/>
|
||||
) : (
|
||||
<McpServerCard
|
||||
key={server.name}
|
||||
key={`${server.name}-${server.scope}`}
|
||||
server={server}
|
||||
isExpanded={currentExpanded.has(server.name)}
|
||||
onToggleExpand={() => currentToggleExpand(server.name)}
|
||||
isExpanded={currentExpanded.has(`${server.name}-${server.scope}`)}
|
||||
onToggleExpand={() => currentToggleExpand(`${server.name}-${server.scope}`)}
|
||||
onToggle={handleToggle}
|
||||
onEdit={handleEdit}
|
||||
onDelete={handleDelete}
|
||||
onSaveAsTemplate={handleSaveServerAsTemplate}
|
||||
conflictInfo={conflictMap.get(server.name)}
|
||||
/>
|
||||
)
|
||||
))}
|
||||
|
||||
Reference in New Issue
Block a user