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.
@@ -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
- import webbrowser
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
- console.print("[yellow]Warning: Visualizer UI assets not found in package. Using fallback static dir.[/yellow]")
362
- # Fallback for development
363
- static_dir = Path.cwd() / "website" / "dist"
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}/playground?{query_string}"
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."""
@@ -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 Playground UI to visualize the code graph.
1002
+ Launches the interactive UI to visualize the code graph.
1003
1003
  """
1004
1004
  _load_credentials()
1005
1005
  visualize_helper(repo, port)