@@ -722,9 +722,76 @@ const GraphRAGPanel: FC = () => {
722722 parts . push ( content . slice ( lastIndex ) ) ;
723723 }
724724
725+ // If no markdown links were found, try to detect owner/repo patterns
726+ if ( parts . length === 1 && typeof parts [ 0 ] === 'string' ) {
727+ return detectAndLinkRepositories ( parts [ 0 ] ) ;
728+ }
729+
725730 return parts . length > 0 ? parts : content ;
726731 } ;
727732
733+ const detectAndLinkRepositories = ( text : string ) => {
734+ // Pattern to match owner/repo format (e.g., "cozodb/cozo", "vmware/differential-datalog")
735+ const repoPattern = / \b ( [ a - z A - Z 0 - 9 ] (?: [ a - z A - Z 0 - 9 ] | - (? = [ a - z A - Z 0 - 9 ] ) ) * ) \/ ( [ a - z A - Z 0 - 9 ] (?: [ a - z A - Z 0 - 9 ] | - (? = [ a - z A - Z 0 - 9 ] ) ) * ) \b / g;
736+ const parts = [ ] ;
737+ let lastIndex = 0 ;
738+ let match ;
739+
740+ while ( ( match = repoPattern . exec ( text ) ) !== null ) {
741+ // Add text before the match
742+ if ( match . index > lastIndex ) {
743+ parts . push ( text . slice ( lastIndex , match . index ) ) ;
744+ }
745+
746+ // Check if this repository exists in the graph
747+ const repoName = match [ 0 ] ; // e.g., "cozodb/cozo"
748+ const nodeId = findNodeByRepoName ( repoName ) ;
749+
750+ if ( nodeId ) {
751+ // Add the clickable link
752+ parts . push (
753+ < button
754+ key = { `repo-link-${ match . index } ` }
755+ className = "btn btn-link p-0 text-decoration-none"
756+ style = { { color : '#007bff' , fontWeight : 'bold' } }
757+ onClick = { ( ) => handleRepoClick ( nodeId ) }
758+ title = { `Click to focus on ${ repoName } in the graph` }
759+ >
760+ { repoName }
761+ </ button >
762+ ) ;
763+ } else {
764+ // Repository not found in graph, just add as text
765+ parts . push ( repoName ) ;
766+ }
767+
768+ lastIndex = match . index + match [ 0 ] . length ;
769+ }
770+
771+ // Add remaining text
772+ if ( lastIndex < text . length ) {
773+ parts . push ( text . slice ( lastIndex ) ) ;
774+ }
775+
776+ return parts . length > 0 ? parts : text ;
777+ } ;
778+
779+ const findNodeByRepoName = ( repoName : string ) : string | null => {
780+ if ( ! data ?. graph ) return null ;
781+
782+ // Search through all nodes to find one with matching label
783+ const nodes = data . graph . nodes ( ) ;
784+ for ( let i = 0 ; i < nodes . length ; i ++ ) {
785+ const nodeId = nodes [ i ] ;
786+ const nodeAttributes = data . graph . getNodeAttributes ( nodeId ) ;
787+ if ( nodeAttributes . label === repoName ) {
788+ return nodeId ;
789+ }
790+ }
791+
792+ return null ;
793+ } ;
794+
728795 const handleRepoClick = ( repoId : string ) => {
729796 // Check if the node exists in the graph
730797 if ( ! data ?. graph . hasNode ( repoId ) ) {
0 commit comments