codegraphcontext 0.3.2__py3-none-any.whl → 0.3.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codegraphcontext/cli/cli_helpers.py +15 -243
- codegraphcontext/cli/main.py +1 -1
- codegraphcontext/cli/visualizer.py +38 -1379
- codegraphcontext/tools/graph_builder.py +76 -60
- codegraphcontext/tools/handlers/query_handlers.py +16 -110
- codegraphcontext/utils/visualize_graph.py +0 -150
- codegraphcontext/viz/server.py +18 -17
- {codegraphcontext-0.3.2.dist-info → codegraphcontext-0.3.3.dist-info}/METADATA +2 -2
- {codegraphcontext-0.3.2.dist-info → codegraphcontext-0.3.3.dist-info}/RECORD +13 -13
- {codegraphcontext-0.3.2.dist-info → codegraphcontext-0.3.3.dist-info}/WHEEL +0 -0
- {codegraphcontext-0.3.2.dist-info → codegraphcontext-0.3.3.dist-info}/entry_points.txt +0 -0
- {codegraphcontext-0.3.2.dist-info → codegraphcontext-0.3.3.dist-info}/licenses/LICENSE +0 -0
- {codegraphcontext-0.3.2.dist-info → codegraphcontext-0.3.3.dist-info}/top_level.txt +0 -0
|
@@ -340,7 +340,9 @@ def cypher_helper_visual(query: str):
|
|
|
340
340
|
console.print(f"[bold red]An error occurred while executing query:[/bold red] {e}")
|
|
341
341
|
finally:
|
|
342
342
|
db_manager.close_driver()
|
|
343
|
-
|
|
343
|
+
|
|
344
|
+
|
|
345
|
+
import uvicorn
|
|
344
346
|
import urllib.parse
|
|
345
347
|
from ..viz.server import run_server, set_db_manager
|
|
346
348
|
|
|
@@ -356,12 +358,18 @@ def visualize_helper(repo_path: Optional[str] = None, port: int = 8000):
|
|
|
356
358
|
set_db_manager(db_manager)
|
|
357
359
|
|
|
358
360
|
# Determine the static directory (built React app)
|
|
361
|
+
# This points to src/codegraphcontext/viz/dist where we build the website
|
|
359
362
|
static_dir = Path(__file__).parent.parent / "viz" / "dist"
|
|
363
|
+
|
|
364
|
+
# Fallback for development if not yet built in viz/dist
|
|
360
365
|
if not static_dir.exists():
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
366
|
+
dev_static_dir = Path.cwd() / "website" / "dist"
|
|
367
|
+
if dev_static_dir.exists():
|
|
368
|
+
static_dir = dev_static_dir
|
|
369
|
+
else:
|
|
370
|
+
console.print("[yellow]Warning: Visualization assets not found. Please run 'cd website && npm run build' first.[/yellow]")
|
|
371
|
+
# We continue anyway to let the server start (helpful for dev)
|
|
372
|
+
|
|
365
373
|
# Construct the URL
|
|
366
374
|
backend_url = f"http://localhost:{port}"
|
|
367
375
|
params = {"backend": backend_url}
|
|
@@ -369,7 +377,7 @@ def visualize_helper(repo_path: Optional[str] = None, port: int = 8000):
|
|
|
369
377
|
params["repo_path"] = str(Path(repo_path).resolve())
|
|
370
378
|
|
|
371
379
|
query_string = urllib.parse.urlencode(params)
|
|
372
|
-
visualization_url = f"{backend_url}/
|
|
380
|
+
visualization_url = f"{backend_url}/explore?{query_string}"
|
|
373
381
|
|
|
374
382
|
console.print(f"[green]Starting visualizer server on {backend_url}...[/green]")
|
|
375
383
|
console.print(f"[cyan]Opening Playground UI:[/cyan] {visualization_url}")
|
|
@@ -377,6 +385,7 @@ def visualize_helper(repo_path: Optional[str] = None, port: int = 8000):
|
|
|
377
385
|
# Open browser in a separate thread/process if possible, or just before starting server
|
|
378
386
|
def open_browser():
|
|
379
387
|
import time
|
|
388
|
+
import webbrowser
|
|
380
389
|
time.sleep(1.5) # Give the server a moment to start
|
|
381
390
|
webbrowser.open(visualization_url)
|
|
382
391
|
|
|
@@ -390,243 +399,6 @@ def visualize_helper(repo_path: Optional[str] = None, port: int = 8000):
|
|
|
390
399
|
finally:
|
|
391
400
|
db_manager.close_driver()
|
|
392
401
|
|
|
393
|
-
def _visualize_falkordb(db_manager):
|
|
394
|
-
console.print("[dim]Generating FalkorDB visualization (showing up to 500 relationships)...[/dim]")
|
|
395
|
-
try:
|
|
396
|
-
data_nodes = []
|
|
397
|
-
data_edges = []
|
|
398
|
-
|
|
399
|
-
with db_manager.get_driver().session() as session:
|
|
400
|
-
# Fetch nodes and edges
|
|
401
|
-
q = "MATCH (n)-[r]->(m) RETURN n, r, m LIMIT 500"
|
|
402
|
-
result = session.run(q)
|
|
403
|
-
|
|
404
|
-
seen_nodes = set()
|
|
405
|
-
|
|
406
|
-
for record in result:
|
|
407
|
-
# record values are Node/Relationship objects from falkordb client
|
|
408
|
-
n = record['n']
|
|
409
|
-
r = record['r']
|
|
410
|
-
m = record['m']
|
|
411
|
-
|
|
412
|
-
# Process Node helper
|
|
413
|
-
def process_node(node):
|
|
414
|
-
nid = getattr(node, 'id', -1)
|
|
415
|
-
labels = getattr(node, 'labels', [])
|
|
416
|
-
lbl = list(labels)[0] if labels else "Node"
|
|
417
|
-
props = getattr(node, 'properties', {})
|
|
418
|
-
name = props.get('name', str(nid))
|
|
419
|
-
|
|
420
|
-
if nid not in seen_nodes:
|
|
421
|
-
seen_nodes.add(nid)
|
|
422
|
-
color = "#97c2fc" # Default blue
|
|
423
|
-
if "Repository" in labels: color = "#ffb3ba" # Red
|
|
424
|
-
elif "File" in labels: color = "#baffc9" # Green
|
|
425
|
-
elif "Class" in labels: color = "#bae1ff" # Light Blue
|
|
426
|
-
elif "Function" in labels: color = "#ffffba" # Yellow
|
|
427
|
-
elif "Package" in labels: color = "#ffdfba" # Orange
|
|
428
|
-
|
|
429
|
-
data_nodes.append({
|
|
430
|
-
"id": nid,
|
|
431
|
-
"label": name,
|
|
432
|
-
"group": lbl,
|
|
433
|
-
"title": str(props),
|
|
434
|
-
"color": color
|
|
435
|
-
})
|
|
436
|
-
return nid
|
|
437
|
-
|
|
438
|
-
nid = process_node(n)
|
|
439
|
-
mid = process_node(m)
|
|
440
|
-
|
|
441
|
-
# Check Edge
|
|
442
|
-
e_type = getattr(r, 'relation', '') or getattr(r, 'type', 'REL')
|
|
443
|
-
data_edges.append({
|
|
444
|
-
"from": nid,
|
|
445
|
-
"to": mid,
|
|
446
|
-
"label": e_type,
|
|
447
|
-
"arrows": "to"
|
|
448
|
-
})
|
|
449
|
-
|
|
450
|
-
filename = "codegraph_viz.html"
|
|
451
|
-
html_content = f"""
|
|
452
|
-
<!DOCTYPE html>
|
|
453
|
-
<html>
|
|
454
|
-
<head>
|
|
455
|
-
<title>CodeGraphContext Visualization</title>
|
|
456
|
-
<script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
|
|
457
|
-
<style type="text/css">
|
|
458
|
-
#mynetwork {{
|
|
459
|
-
width: 100%;
|
|
460
|
-
height: 100vh;
|
|
461
|
-
border: 1px solid lightgray;
|
|
462
|
-
}}
|
|
463
|
-
</style>
|
|
464
|
-
</head>
|
|
465
|
-
<body>
|
|
466
|
-
<div id="mynetwork"></div>
|
|
467
|
-
<script type="text/javascript">
|
|
468
|
-
var nodes = new vis.DataSet({json.dumps(data_nodes)});
|
|
469
|
-
var edges = new vis.DataSet({json.dumps(data_edges)});
|
|
470
|
-
var container = document.getElementById('mynetwork');
|
|
471
|
-
var data = {{ nodes: nodes, edges: edges }};
|
|
472
|
-
var options = {{
|
|
473
|
-
nodes: {{ shape: 'dot', size: 16 }},
|
|
474
|
-
physics: {{ stabilization: false }},
|
|
475
|
-
layout: {{ improvedLayout: false }}
|
|
476
|
-
}};
|
|
477
|
-
var network = new vis.Network(container, data, options);
|
|
478
|
-
</script>
|
|
479
|
-
</body>
|
|
480
|
-
</html>
|
|
481
|
-
"""
|
|
482
|
-
|
|
483
|
-
out_path = Path(filename).resolve()
|
|
484
|
-
with open(out_path, "w") as f:
|
|
485
|
-
f.write(html_content)
|
|
486
|
-
|
|
487
|
-
console.print(f"[green]Visualization generated at:[/green] {out_path}")
|
|
488
|
-
console.print("Opening in default browser...")
|
|
489
|
-
webbrowser.open(f"file://{out_path}")
|
|
490
|
-
|
|
491
|
-
except Exception as e:
|
|
492
|
-
console.print(f"[bold red]Visualization failed:[/bold red] {e}")
|
|
493
|
-
import traceback
|
|
494
|
-
traceback.print_exc()
|
|
495
|
-
finally:
|
|
496
|
-
db_manager.close_driver()
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
def _visualize_kuzudb(db_manager):
|
|
500
|
-
console.print("[dim]Generating KùzuDB visualization (showing up to 500 relationships)...[/dim]")
|
|
501
|
-
try:
|
|
502
|
-
data_nodes = []
|
|
503
|
-
data_edges = []
|
|
504
|
-
|
|
505
|
-
with db_manager.get_driver().session() as session:
|
|
506
|
-
# Fetch nodes and edges
|
|
507
|
-
# KùzuDB returns dicts for n, r, m in the result
|
|
508
|
-
q = "MATCH (n)-[r]->(m) RETURN n, r, m LIMIT 500"
|
|
509
|
-
result = session.run(q)
|
|
510
|
-
|
|
511
|
-
seen_nodes = set()
|
|
512
|
-
|
|
513
|
-
# Helper to extract Node ID and props
|
|
514
|
-
def process_node(node):
|
|
515
|
-
uid = None
|
|
516
|
-
lbl = 'Node'
|
|
517
|
-
props = {}
|
|
518
|
-
|
|
519
|
-
# Handle Kuzu Node Object (processed by wrapper)
|
|
520
|
-
if hasattr(node, 'properties'):
|
|
521
|
-
props = node.properties or {}
|
|
522
|
-
if hasattr(node, 'labels') and node.labels:
|
|
523
|
-
lbl = node.labels[0]
|
|
524
|
-
if hasattr(node, 'id'):
|
|
525
|
-
uid = str(node.id)
|
|
526
|
-
# Handle Dictionary (raw Kuzu result)
|
|
527
|
-
elif isinstance(node, dict):
|
|
528
|
-
if '_id' in node:
|
|
529
|
-
uid = f"{node['_id']['table']}_{node['_id']['offset']}"
|
|
530
|
-
lbl = node.get('_label', 'Node')
|
|
531
|
-
props = {k: v for k, v in node.items() if not k.startswith('_')}
|
|
532
|
-
|
|
533
|
-
if not uid:
|
|
534
|
-
uid = str(uuid.uuid4())
|
|
535
|
-
|
|
536
|
-
name = props.get('name', str(uid))
|
|
537
|
-
|
|
538
|
-
if uid not in seen_nodes:
|
|
539
|
-
seen_nodes.add(uid)
|
|
540
|
-
color = "#97c2fc" # Default blue
|
|
541
|
-
if "Repository" == lbl: color = "#ffb3ba"
|
|
542
|
-
elif "File" == lbl: color = "#baffc9"
|
|
543
|
-
elif "Class" == lbl: color = "#bae1ff"
|
|
544
|
-
elif "Function" == lbl: color = "#ffffba"
|
|
545
|
-
elif "Module" == lbl: color = "#ffdfba"
|
|
546
|
-
|
|
547
|
-
data_nodes.append({
|
|
548
|
-
"id": uid,
|
|
549
|
-
"label": name,
|
|
550
|
-
"group": lbl,
|
|
551
|
-
"title": str(props),
|
|
552
|
-
"color": color
|
|
553
|
-
})
|
|
554
|
-
return uid
|
|
555
|
-
|
|
556
|
-
# Iterate results
|
|
557
|
-
for record in result:
|
|
558
|
-
# record is dict-like access to row items
|
|
559
|
-
n = record['n']
|
|
560
|
-
r = record['r']
|
|
561
|
-
m = record['m']
|
|
562
|
-
|
|
563
|
-
nid = process_node(n)
|
|
564
|
-
mid = process_node(m)
|
|
565
|
-
|
|
566
|
-
# Process Edge
|
|
567
|
-
e_type = 'REL'
|
|
568
|
-
if hasattr(r, 'type'):
|
|
569
|
-
e_type = r.type
|
|
570
|
-
elif isinstance(r, dict):
|
|
571
|
-
e_type = r.get('_label', 'REL')
|
|
572
|
-
elif hasattr(r, 'label'): # Some versions
|
|
573
|
-
e_type = r.label
|
|
574
|
-
|
|
575
|
-
data_edges.append({
|
|
576
|
-
"from": nid,
|
|
577
|
-
"to": mid,
|
|
578
|
-
"label": e_type,
|
|
579
|
-
"arrows": "to"
|
|
580
|
-
})
|
|
581
|
-
|
|
582
|
-
filename = "codegraph_viz.html"
|
|
583
|
-
html_content = f"""
|
|
584
|
-
<!DOCTYPE html>
|
|
585
|
-
<html>
|
|
586
|
-
<head>
|
|
587
|
-
<title>CodeGraphContext KùzuDB Visualization</title>
|
|
588
|
-
<script type="text/javascript" src="https://unpkg.com/vis-network/standalone/umd/vis-network.min.js"></script>
|
|
589
|
-
<style type="text/css">
|
|
590
|
-
#mynetwork {{
|
|
591
|
-
width: 100%;
|
|
592
|
-
height: 100vh;
|
|
593
|
-
border: 1px solid lightgray;
|
|
594
|
-
}}
|
|
595
|
-
</style>
|
|
596
|
-
</head>
|
|
597
|
-
<body>
|
|
598
|
-
<div id="mynetwork"></div>
|
|
599
|
-
<script type="text/javascript">
|
|
600
|
-
var nodes = new vis.DataSet({json.dumps(data_nodes)});
|
|
601
|
-
var edges = new vis.DataSet({json.dumps(data_edges)});
|
|
602
|
-
var container = document.getElementById('mynetwork');
|
|
603
|
-
var data = {{ nodes: nodes, edges: edges }};
|
|
604
|
-
var options = {{
|
|
605
|
-
nodes: {{ shape: 'dot', size: 16 }},
|
|
606
|
-
physics: {{ stabilization: false }},
|
|
607
|
-
layout: {{ improvedLayout: false }}
|
|
608
|
-
}};
|
|
609
|
-
var network = new vis.Network(container, data, options);
|
|
610
|
-
</script>
|
|
611
|
-
</body>
|
|
612
|
-
</html>
|
|
613
|
-
"""
|
|
614
|
-
|
|
615
|
-
out_path = Path(filename).resolve()
|
|
616
|
-
with open(out_path, "w") as f:
|
|
617
|
-
f.write(html_content)
|
|
618
|
-
|
|
619
|
-
console.print(f"[green]Visualization generated at:[/green] {out_path}")
|
|
620
|
-
console.print("Opening in default browser...")
|
|
621
|
-
webbrowser.open(f"file://{out_path}")
|
|
622
|
-
|
|
623
|
-
except Exception as e:
|
|
624
|
-
console.print(f"[bold red]Visualization failed:[/bold red] {e}")
|
|
625
|
-
import traceback
|
|
626
|
-
traceback.print_exc()
|
|
627
|
-
finally:
|
|
628
|
-
db_manager.close_driver()
|
|
629
|
-
|
|
630
402
|
|
|
631
403
|
def reindex_helper(path: str):
|
|
632
404
|
"""Force re-index by deleting and rebuilding the repository."""
|
codegraphcontext/cli/main.py
CHANGED
|
@@ -999,7 +999,7 @@ def visualize(
|
|
|
999
999
|
port: int = typer.Option(8000, "--port", "-p", help="Port to run the visualizer server on.")
|
|
1000
1000
|
):
|
|
1001
1001
|
"""
|
|
1002
|
-
Launches the interactive
|
|
1002
|
+
Launches the interactive UI to visualize the code graph.
|
|
1003
1003
|
"""
|
|
1004
1004
|
_load_credentials()
|
|
1005
1005
|
visualize_helper(repo, port)
|