MCPcopy Create free account
hub / github.com/codag-megalith/codag-visualizer / getMergedGraph

Method getMergedGraph

frontend/src/cache.ts:746–924  ·  view source on GitHub ↗

* Get merged graph for display from cached files

(filePaths?: string[])

Source from the content-addressed store, hash-verified

744 * Get merged graph for display from cached files
745 */
746 async getMergedGraph(filePaths?: string[]): Promise<WorkflowGraph | null> {
747 await this.initPromise;
748
749 // Normalize input paths to relative paths (cache keys are always relative)
750 const targetFiles = filePaths
751 ? filePaths.map(fp => this.toRelativePath(fp))
752 : Object.keys(this.files);
753 const allNodes: WorkflowNode[] = [];
754 const allEdges: WorkflowEdge[] = [];
755 const nodeIds = new Set<string>();
756 const llmsDetected = new Set<string>();
757
758 // Collect from cached files (dedupe nodes by ID, keep most complete)
759 const nodeById = new Map<string, WorkflowNode>();
760 for (const fp of targetFiles) {
761 const cached = this.files[fp];
762 if (cached) {
763 for (const node of cached.nodes) {
764 const existing = nodeById.get(node.id);
765 // Keep node with more complete info (has source.line vs doesn't)
766 if (!existing || (node.source?.line && !existing.source?.line)) {
767 nodeById.set(node.id, node);
768 }
769 nodeIds.add(node.id);
770 if (node.model) llmsDetected.add(node.model);
771 }
772 allEdges.push(...cached.internalEdges);
773 }
774 }
775 allNodes.push(...nodeById.values());
776
777 // Sanitize purely-numeric labels (LLM sometimes returns sequence numbers instead of names).
778 // Replace with the function name from source metadata.
779 for (const node of allNodes) {
780 if (/^\d+$/.test(node.label) && node.source?.function) {
781 node.label = node.source.function.replace(/\(\)$/, '');
782 }
783 }
784
785 if (allNodes.length === 0) return null;
786
787 // Add valid cross-file edges with fuzzy ID resolution
788 // This handles cases where LLM uses shortened paths (e.g., "file.py::func")
789 // but actual node IDs have full paths (e.g., "dir/file.py::func")
790 const lookup = buildNodeLookup(allNodes);
791 for (const edge of this.crossFileEdges) {
792 let resolvedSource = findMatchingNodeId(edge.sourceNodeId, lookup);
793 let resolvedTarget = findMatchingNodeId(edge.targetNodeId, lookup);
794
795 // Create stub node for cross-file edge targets that don't exist as cached nodes.
796 if (resolvedSource && !resolvedTarget) {
797 const targetId = edge.targetNodeId;
798 const parts = targetId.split('::');
799 const isRealFile = parts.length >= 2 && /\.\w+$/.test(parts[0]);
800
801 let stubNode: WorkflowNode | null = null;
802
803 if (isRealFile) {

Callers 5

activateFunction · 0.95
analyzeSelectedFilesFunction · 0.80
analyzeWorkspaceFunction · 0.80
performLocalUpdateFunction · 0.80

Calls 10

toRelativePathMethod · 0.95
computeWorkflowsMethod · 0.95
writeGraphFileMethod · 0.95
buildNodeLookupFunction · 0.90
findMatchingNodeIdFunction · 0.90
setMethod · 0.80
getMethod · 0.45
addMethod · 0.45
hasMethod · 0.45
fromMethod · 0.45

Tested by

no test coverage detected