codegraphcontext 0.3.0__tar.gz → 0.3.2__tar.gz

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.
Files changed (87) hide show
  1. codegraphcontext-0.3.2/MANIFEST.in +5 -0
  2. {codegraphcontext-0.3.0/src/codegraphcontext.egg-info → codegraphcontext-0.3.2}/PKG-INFO +17 -4
  3. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/README.md +14 -2
  4. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/pyproject.toml +8 -3
  5. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/cli/cli_helpers.py +42 -30
  6. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/cli/main.py +12 -8
  7. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/core/cgc_bundle.py +5 -1
  8. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/code_finder.py +25 -26
  9. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/graph_builder.py +157 -6
  10. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/package_resolver.py +12 -10
  11. codegraphcontext-0.3.2/src/codegraphcontext/viz/server.py +178 -0
  12. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2/src/codegraphcontext.egg-info}/PKG-INFO +17 -4
  13. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext.egg-info/SOURCES.txt +2 -1
  14. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext.egg-info/requires.txt +2 -1
  15. codegraphcontext-0.3.0/MANIFEST.in +0 -4
  16. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/LICENSE +0 -0
  17. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/setup.cfg +0 -0
  18. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/__init__.py +0 -0
  19. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/__main__.py +0 -0
  20. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/cli/__init__.py +0 -0
  21. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/cli/config_manager.py +0 -0
  22. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/cli/registry_commands.py +0 -0
  23. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/cli/setup_macos.py +0 -0
  24. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/cli/setup_wizard.py +0 -0
  25. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/cli/visualizer.py +0 -0
  26. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/core/__init__.py +0 -0
  27. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/core/bundle_registry.py +0 -0
  28. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/core/database.py +0 -0
  29. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/core/database_falkordb.py +0 -0
  30. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/core/database_falkordb_remote.py +0 -0
  31. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/core/database_kuzu.py +0 -0
  32. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/core/falkor_worker.py +0 -0
  33. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/core/jobs.py +0 -0
  34. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/core/watcher.py +0 -0
  35. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/prompts.py +0 -0
  36. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/server.py +0 -0
  37. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tool_definitions.py +0 -0
  38. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/__init__.py +0 -0
  39. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/advanced_language_query_tool.py +0 -0
  40. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/handlers/analysis_handlers.py +0 -0
  41. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/handlers/indexing_handlers.py +0 -0
  42. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/handlers/management_handlers.py +0 -0
  43. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/handlers/query_handlers.py +0 -0
  44. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/handlers/watcher_handlers.py +0 -0
  45. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/c.py +0 -0
  46. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/cpp.py +0 -0
  47. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/csharp.py +0 -0
  48. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/dart.py +0 -0
  49. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/elixir.py +0 -0
  50. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/go.py +0 -0
  51. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/haskell.py +0 -0
  52. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/java.py +0 -0
  53. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/javascript.py +0 -0
  54. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/kotlin.py +0 -0
  55. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/perl.py +0 -0
  56. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/php.py +0 -0
  57. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/python.py +0 -0
  58. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/ruby.py +0 -0
  59. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/rust.py +0 -0
  60. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/scala.py +0 -0
  61. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/swift.py +0 -0
  62. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/typescript.py +0 -0
  63. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/languages/typescriptjsx.py +0 -0
  64. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/c_toolkit.py +0 -0
  65. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +0 -0
  66. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +0 -0
  67. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/dart_toolkit.py +0 -0
  68. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/go_toolkit.py +0 -0
  69. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/haskell_toolkit.py +0 -0
  70. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/java_toolkit.py +0 -0
  71. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +0 -0
  72. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/perl_toolkit.py +0 -0
  73. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/python_toolkit.py +0 -0
  74. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +0 -0
  75. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/rust_toolkit.py +0 -0
  76. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/scala_toolkit.py +0 -0
  77. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/swift_toolkit.py +0 -0
  78. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +0 -0
  79. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/scip_indexer.py +0 -0
  80. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/scip_pb2.py +0 -0
  81. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/tools/system.py +0 -0
  82. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/utils/debug_log.py +0 -0
  83. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/utils/tree_sitter_manager.py +0 -0
  84. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext/utils/visualize_graph.py +0 -0
  85. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext.egg-info/dependency_links.txt +0 -0
  86. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext.egg-info/entry_points.txt +0 -0
  87. {codegraphcontext-0.3.0 → codegraphcontext-0.3.2}/src/codegraphcontext.egg-info/top_level.txt +0 -0
@@ -0,0 +1,5 @@
1
+ prune website
2
+ prune images
3
+ prune vscode-extension
4
+ prune playground
5
+ recursive-include src/codegraphcontext/viz/dist *
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraphcontext
3
- Version: 0.3.0
3
+ Version: 0.3.2
4
4
  Summary: An MCP server that indexes local code into a graph database to provide context to AI assistants.
5
5
  Author-email: Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
6
6
  License: MIT License
@@ -46,12 +46,13 @@ Requires-Dist: python-dotenv>=1.0.0
46
46
  Requires-Dist: tree-sitter>=0.21.0
47
47
  Requires-Dist: tree-sitter-language-pack>=0.6.0
48
48
  Requires-Dist: pyyaml
49
- Requires-Dist: pytest
50
49
  Requires-Dist: nbformat
51
50
  Requires-Dist: nbconvert>=7.16.6
52
51
  Requires-Dist: pathspec>=0.12.1
53
52
  Requires-Dist: falkordb>=0.1.0
54
53
  Requires-Dist: falkordblite>=0.1.0; sys_platform != "win32" and python_version >= "3.12"
54
+ Requires-Dist: fastapi>=0.100.0
55
+ Requires-Dist: uvicorn>=0.22.0
55
56
  Provides-Extra: parsing
56
57
  Requires-Dist: tree-sitter>=0.21.0; extra == "parsing"
57
58
  Requires-Dist: tree-sitter-language-pack>=0.6.0; extra == "parsing"
@@ -63,6 +64,18 @@ Dynamic: license-file
63
64
 
64
65
  # 🏗️ CodeGraphContext (CGC)
65
66
 
67
+ **Turn code repositories into a queryable graph for AI agents.**
68
+
69
+ 🌐 **Languages:**
70
+ - 🇬🇧 [English](README.md)
71
+ - 🇨🇳 [中文](README.zh-CN.md)
72
+ - 🇰🇷 [한국어](README.kor.md)
73
+ - 🇯🇵 日本語 (Soon)
74
+ - 🇷🇺 Русский (Soon)
75
+ - 🇪🇸 Español (Soon)
76
+
77
+ 🌍 **Help translate CodeGraphContext to your language by raising an issue & PR on https://github.com/Shashankss1205/CodeGraphContext/issues!**
78
+
66
79
  <p align="center">
67
80
  <br>
68
81
  <b>Bridge the gap between deep code graphs and AI context.</b>
@@ -147,7 +160,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
147
160
  ---
148
161
 
149
162
  ## Project Details
150
- - **Version:** 0.3.0
163
+ - **Version:** 0.3.2
151
164
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
152
165
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
153
166
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -352,7 +365,7 @@ cgc watch .
352
365
  cgc help
353
366
  ```
354
367
 
355
- **See the full [CLI Commands Guide](CLI_Commands.md) for all available commands and usage scenarios.**
368
+ **See the full [CLI Commands Guide](docs/CLI_COMPLETE_REFERENCE.md) for all available commands and usage scenarios.**
356
369
 
357
370
  ### 🎨 Premium Interactive Visualization
358
371
  CodeGraphContext can generate stunning, interactive knowledge graphs of your code. Unlike static diagrams, these are premium web-based explorers:
@@ -1,5 +1,17 @@
1
1
  # 🏗️ CodeGraphContext (CGC)
2
2
 
3
+ **Turn code repositories into a queryable graph for AI agents.**
4
+
5
+ 🌐 **Languages:**
6
+ - 🇬🇧 [English](README.md)
7
+ - 🇨🇳 [中文](README.zh-CN.md)
8
+ - 🇰🇷 [한국어](README.kor.md)
9
+ - 🇯🇵 日本語 (Soon)
10
+ - 🇷🇺 Русский (Soon)
11
+ - 🇪🇸 Español (Soon)
12
+
13
+ 🌍 **Help translate CodeGraphContext to your language by raising an issue & PR on https://github.com/Shashankss1205/CodeGraphContext/issues!**
14
+
3
15
  <p align="center">
4
16
  <br>
5
17
  <b>Bridge the gap between deep code graphs and AI context.</b>
@@ -84,7 +96,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
84
96
  ---
85
97
 
86
98
  ## Project Details
87
- - **Version:** 0.3.0
99
+ - **Version:** 0.3.2
88
100
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
89
101
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
90
102
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -289,7 +301,7 @@ cgc watch .
289
301
  cgc help
290
302
  ```
291
303
 
292
- **See the full [CLI Commands Guide](CLI_Commands.md) for all available commands and usage scenarios.**
304
+ **See the full [CLI Commands Guide](docs/CLI_COMPLETE_REFERENCE.md) for all available commands and usage scenarios.**
293
305
 
294
306
  ### 🎨 Premium Interactive Visualization
295
307
  CodeGraphContext can generate stunning, interactive knowledge graphs of your code. Unlike static diagrams, these are premium web-based explorers:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codegraphcontext"
3
- version = "0.3.0"
3
+ version = "0.3.2"
4
4
  description = "An MCP server that indexes local code into a graph database to provide context to AI assistants."
5
5
  authors = [{ name = "Shashank Shekhar Singh", email = "shashankshekharsingh1205@gmail.com" }]
6
6
  readme = "README.md"
@@ -25,12 +25,13 @@ dependencies = [
25
25
  "tree-sitter>=0.21.0",
26
26
  "tree-sitter-language-pack>=0.6.0",
27
27
  "pyyaml",
28
- "pytest",
29
28
  "nbformat",
30
29
  "nbconvert>=7.16.6",
31
30
  "pathspec>=0.12.1",
32
31
  "falkordb>=0.1.0",
33
- "falkordblite>=0.1.0; sys_platform != 'win32' and python_version >= '3.12'"
32
+ "falkordblite>=0.1.0; sys_platform != 'win32' and python_version >= '3.12'",
33
+ "fastapi>=0.100.0",
34
+ "uvicorn>=0.22.0"
34
35
  ]
35
36
 
36
37
  [project.optional-dependencies]
@@ -54,6 +55,10 @@ codegraphcontext = "codegraphcontext.cli.main:app"
54
55
 
55
56
  [tool.setuptools]
56
57
  package-dir = { "" = "src" }
58
+ include-package-data = true
59
+
60
+ [tool.setuptools.package-data]
61
+ codegraphcontext = ["viz/dist/**/*"]
57
62
 
58
63
  [tool.setuptools.packages.find]
59
64
  where = ["src"]
@@ -4,6 +4,7 @@ import uuid
4
4
  import urllib.parse
5
5
  from pathlib import Path
6
6
  import time
7
+ from typing import Optional
7
8
  from rich.console import Console
8
9
  from rich.table import Table
9
10
  from rich.progress import (
@@ -339,44 +340,55 @@ def cypher_helper_visual(query: str):
339
340
  console.print(f"[bold red]An error occurred while executing query:[/bold red] {e}")
340
341
  finally:
341
342
  db_manager.close_driver()
342
-
343
-
344
343
  import webbrowser
344
+ import urllib.parse
345
+ from ..viz.server import run_server, set_db_manager
345
346
 
346
- def visualize_helper(query: str):
347
- """"Generates a visualization."""
347
+ def visualize_helper(repo_path: Optional[str] = None, port: int = 8000):
348
+ """"Generates an interactive visualization using the Playground UI."""
348
349
  services = _initialize_services()
349
350
  if not all(services):
350
351
  return
351
352
 
352
353
  db_manager, _, _ = services
353
354
 
354
- # Check Backend Type
355
- backend = getattr(db_manager, "name", "").lower()
356
- if not backend:
357
- # Fallback check
358
- if "FalkorDB" in db_manager.__class__.__name__:
359
- backend = "falkordb"
360
- elif "Kuzu" in db_manager.__class__.__name__:
361
- backend = "kuzudb"
362
- else:
363
- backend = "neo4j"
364
-
365
- if backend == "falkordb":
366
- _visualize_falkordb(db_manager)
367
- elif backend == "kuzudb":
368
- _visualize_kuzudb(db_manager)
369
- else:
370
- try:
371
- encoded_query = urllib.parse.quote(query)
372
- visualization_url = f"http://localhost:7474/browser/?cmd=edit&arg={encoded_query}"
373
- console.print("[green]Graph visualization URL:[/green]")
374
- console.print(visualization_url)
375
- console.print("Open the URL in your browser to see the graph.")
376
- except Exception as e:
377
- console.print(f"[bold red]An error occurred while generating URL:[/bold red] {e}")
378
- finally:
379
- db_manager.close_driver()
355
+ # Set the DB manager for the server
356
+ set_db_manager(db_manager)
357
+
358
+ # Determine the static directory (built React app)
359
+ static_dir = Path(__file__).parent.parent / "viz" / "dist"
360
+ 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
+
365
+ # Construct the URL
366
+ backend_url = f"http://localhost:{port}"
367
+ params = {"backend": backend_url}
368
+ if repo_path:
369
+ params["repo_path"] = str(Path(repo_path).resolve())
370
+
371
+ query_string = urllib.parse.urlencode(params)
372
+ visualization_url = f"{backend_url}/playground?{query_string}"
373
+
374
+ console.print(f"[green]Starting visualizer server on {backend_url}...[/green]")
375
+ console.print(f"[cyan]Opening Playground UI:[/cyan] {visualization_url}")
376
+
377
+ # Open browser in a separate thread/process if possible, or just before starting server
378
+ def open_browser():
379
+ import time
380
+ time.sleep(1.5) # Give the server a moment to start
381
+ webbrowser.open(visualization_url)
382
+
383
+ import threading
384
+ threading.Thread(target=open_browser, daemon=True).start()
385
+
386
+ try:
387
+ run_server(host="127.0.0.1", port=port, static_dir=str(static_dir))
388
+ except Exception as e:
389
+ console.print(f"[bold red]An error occurred while running the server:[/bold red] {e}")
390
+ finally:
391
+ db_manager.close_driver()
380
392
 
381
393
  def _visualize_falkordb(db_manager):
382
394
  console.print("[dim]Generating FalkorDB visualization (showing up to 500 relationships)...[/dim]")
@@ -994,15 +994,15 @@ def delete(
994
994
  delete_helper(path)
995
995
 
996
996
  @app.command()
997
- def visualize(query: Optional[str] = typer.Argument(None, help="The Cypher query to visualize.")):
997
+ def visualize(
998
+ repo: Optional[str] = typer.Option(None, "--repo", "-r", help="Path to the repository to visualize."),
999
+ port: int = typer.Option(8000, "--port", "-p", help="Port to run the visualizer server on.")
1000
+ ):
998
1001
  """
999
- Generates a URL to visualize a Cypher query in the Neo4j Browser.
1000
- If no query is provided, a default query will be used.
1002
+ Launches the interactive Playground UI to visualize the code graph.
1001
1003
  """
1002
- if query is None:
1003
- query = "MATCH p=()-->() RETURN p"
1004
1004
  _load_credentials()
1005
- visualize_helper(query)
1005
+ visualize_helper(repo, port)
1006
1006
 
1007
1007
  @app.command("list")
1008
1008
  def list_repositories():
@@ -2145,9 +2145,13 @@ def delete_abbrev(
2145
2145
  delete(path, all_repos)
2146
2146
 
2147
2147
  @app.command("v", rich_help_panel="Shortcuts")
2148
- def visualize_abbrev(query: Optional[str] = typer.Argument(None, help="Cypher query")):
2148
+ def visualize_abbrev(
2149
+ repo: Optional[str] = typer.Argument(None, help="Path to the repository to visualize."),
2150
+ port: int = typer.Option(8000, "--port", "-p", help="Port to run the visualizer server on.")
2151
+ ):
2149
2152
  """Shortcut for 'cgc visualize'"""
2150
- visualize(query)
2153
+ _load_credentials()
2154
+ visualize_helper(repo, port)
2151
2155
 
2152
2156
  @app.command("w", rich_help_panel="Shortcuts")
2153
2157
  def watch_abbrev(path: str = typer.Argument(".", help="Path to watch")):
@@ -161,9 +161,13 @@ class CGCBundle:
161
161
  with tempfile.TemporaryDirectory() as temp_dir:
162
162
  temp_path = Path(temp_dir)
163
163
 
164
- # Step 1: Extract ZIP
164
+ # Step 1: Extract ZIP (with Zip Slip protection)
165
165
  info_logger("Extracting bundle...")
166
166
  with zipfile.ZipFile(bundle_path, 'r') as zip_ref:
167
+ for entry in zip_ref.namelist():
168
+ resolved = (temp_path / entry).resolve()
169
+ if not str(resolved).startswith(str(temp_path.resolve())):
170
+ return False, f"Zip Slip detected: entry '{entry}' escapes target directory"
167
171
  zip_ref.extractall(temp_path)
168
172
 
169
173
  # Step 2: Validate bundle
@@ -1,6 +1,6 @@
1
1
  # src/codegraphcontext/tools/code_finder.py
2
2
  import logging
3
- import re
3
+
4
4
  from typing import Any, Dict, List, Literal, Optional
5
5
  from pathlib import Path
6
6
 
@@ -348,7 +348,6 @@ class CodeFinder:
348
348
  def what_does_function_call(self, function_name: str, path: Optional[str] = None, repo_path: Optional[str] = None) -> List[Dict]:
349
349
  """Find what functions a specific function calls using CALLS relationships"""
350
350
  with self.driver.session() as session:
351
- repo_filter = "AND called.path STARTS WITH $repo_path" if repo_path else ""
352
351
  if path:
353
352
  # Convert path to absolute path
354
353
  absolute_file_path = str(Path(path).resolve())
@@ -450,16 +449,16 @@ class CodeFinder:
450
449
  def find_class_hierarchy(self, class_name: str, path: Optional[str] = None, repo_path: Optional[str] = None) -> Dict[str, Any]:
451
450
  """Find class inheritance relationships using INHERITS relationships"""
452
451
  with self.driver.session() as session:
453
- repo_filter = "WHERE 1=1 AND parent.path STARTS WITH $repo_path" if repo_path else ""
452
+ repo_filter = "AND parent.path STARTS WITH $repo_path" if repo_path else ""
454
453
  if path:
455
454
  match_clause = "MATCH (child:Class {name: $class_name, path: $path})"
456
455
  else:
457
456
  match_clause = "MATCH (child:Class {name: $class_name})"
458
457
 
459
458
  parents_query = f"""
460
- {{match_clause}}
459
+ {match_clause}
461
460
  MATCH (child)-[:INHERITS]->(parent:Class)
462
- WHERE 1=1 {{repo_filter}}
461
+ WHERE 1=1 {repo_filter}
463
462
  OPTIONAL MATCH (parent_file:File)-[:CONTAINS]->(parent)
464
463
  RETURN DISTINCT
465
464
  parent.name as parent_class,
@@ -471,11 +470,11 @@ class CodeFinder:
471
470
  """
472
471
  parents_result = session.run(parents_query, class_name=class_name, path=path, repo_path=repo_path)
473
472
 
474
- repo_filter_child = "WHERE 1=1 AND grandchild.path STARTS WITH $repo_path" if repo_path else ""
473
+ repo_filter_child = "AND grandchild.path STARTS WITH $repo_path" if repo_path else ""
475
474
  children_query = f"""
476
- {{match_clause}}
475
+ {match_clause}
477
476
  MATCH (grandchild:Class)-[:INHERITS]->(child)
478
- WHERE 1=1 {{repo_filter_child}}
477
+ WHERE 1=1 {repo_filter_child}
479
478
  OPTIONAL MATCH (child_file:File)-[:CONTAINS]->(grandchild)
480
479
  RETURN DISTINCT
481
480
  grandchild.name as child_class,
@@ -513,10 +512,10 @@ class CodeFinder:
513
512
  def find_function_overrides(self, function_name: str, repo_path: Optional[str] = None) -> List[Dict]:
514
513
  """Find all implementations of a function across different classes"""
515
514
  with self.driver.session() as session:
516
- repo_filter = "WHERE 1=1 AND class.path STARTS WITH $repo_path" if repo_path else ""
515
+ repo_filter = "AND class.path STARTS WITH $repo_path" if repo_path else ""
517
516
  result = session.run(f"""
518
517
  MATCH (class:Class)-[:CONTAINS]->(func:Function {{name: $function_name}})
519
- WHERE 1=1 {{repo_filter}}
518
+ WHERE 1=1 {repo_filter}
520
519
  OPTIONAL MATCH (file:File)-[:CONTAINS]->(class)
521
520
  RETURN DISTINCT
522
521
  class.name as class_name,
@@ -821,69 +820,69 @@ class CodeFinder:
821
820
  "instances": variable_instances.data()
822
821
  }
823
822
 
824
- def analyze_code_relationships(self, query_type: str, target: str, context: Optional[str] = None) -> Dict[str, Any]:
823
+ def analyze_code_relationships(self, query_type: str, target: str, context: Optional[str] = None, repo_path: Optional[str] = None) -> Dict[str, Any]:
825
824
  """Main method to analyze different types of code relationships with fixed return types"""
826
825
  query_type = query_type.lower().strip()
827
826
 
828
827
  try:
829
828
  if query_type == "find_callers":
830
- results = self.who_calls_function(target, context)
829
+ results = self.who_calls_function(target, context, repo_path=repo_path)
831
830
  return {
832
831
  "query_type": "find_callers", "target": target, "context": context, "results": results,
833
832
  "summary": f"Found {len(results)} functions that call '{target}'"
834
833
  }
835
834
 
836
835
  elif query_type == "find_callees":
837
- results = self.what_does_function_call(target, context)
836
+ results = self.what_does_function_call(target, context, repo_path=repo_path)
838
837
  return {
839
838
  "query_type": "find_callees", "target": target, "context": context, "results": results,
840
839
  "summary": f"Function '{target}' calls {len(results)} other functions"
841
840
  }
842
841
 
843
842
  elif query_type == "find_importers":
844
- results = self.who_imports_module(target)
843
+ results = self.who_imports_module(target, repo_path=repo_path)
845
844
  return {
846
845
  "query_type": "find_importers", "target": target, "results": results,
847
846
  "summary": f"Found {len(results)} files that import '{target}'"
848
847
  }
849
848
 
850
849
  elif query_type == "find_functions_by_argument":
851
- results = self.find_functions_by_argument(target, context)
850
+ results = self.find_functions_by_argument(target, context, repo_path=repo_path)
852
851
  return {
853
852
  "query_type": "find_functions_by_argument", "target": target, "context": context, "results": results,
854
853
  "summary": f"Found {len(results)} functions that take '{target}' as an argument"
855
854
  }
856
855
 
857
856
  elif query_type == "find_functions_by_decorator":
858
- results = self.find_functions_by_decorator(target, context)
857
+ results = self.find_functions_by_decorator(target, context, repo_path=repo_path)
859
858
  return {
860
859
  "query_type": "find_functions_by_decorator", "target": target, "context": context, "results": results,
861
860
  "summary": f"Found {len(results)} functions decorated with '{target}'"
862
861
  }
863
862
 
864
863
  elif query_type in ["who_modifies", "modifies", "mutations", "changes", "variable_usage"]:
865
- results = self.who_modifies_variable(target)
864
+ results = self.who_modifies_variable(target, repo_path=repo_path)
866
865
  return {
867
866
  "query_type": "who_modifies", "target": target, "results": results,
868
867
  "summary": f"Found {len(results)} containers that hold variable '{target}'"
869
868
  }
870
869
 
871
870
  elif query_type in ["class_hierarchy", "inheritance", "extends"]:
872
- results = self.find_class_hierarchy(target, context)
871
+ results = self.find_class_hierarchy(target, context, repo_path=repo_path)
873
872
  return {
874
873
  "query_type": "class_hierarchy", "target": target, "results": results,
875
874
  "summary": f"Class '{target}' has {len(results['parent_classes'])} parents, {len(results['child_classes'])} children, and {len(results['methods'])} methods"
876
875
  }
877
876
 
878
877
  elif query_type in ["overrides", "implementations", "polymorphism"]:
879
- results = self.find_function_overrides(target)
878
+ results = self.find_function_overrides(target, repo_path=repo_path)
880
879
  return {
881
880
  "query_type": "overrides", "target": target, "results": results,
882
881
  "summary": f"Found {len(results)} implementations of function '{target}'"
883
882
  }
884
883
 
885
884
  elif query_type in ["dead_code", "unused", "unreachable"]:
886
- results = self.find_dead_code()
885
+ results = self.find_dead_code(repo_path=repo_path)
887
886
  return {
888
887
  "query_type": "dead_code", "results": results,
889
888
  "summary": f"Found {len(results['potentially_unused_functions'])} potentially unused functions"
@@ -891,21 +890,21 @@ class CodeFinder:
891
890
 
892
891
  elif query_type == "find_complexity":
893
892
  limit = int(context) if context and context.isdigit() else 10
894
- results = self.find_most_complex_functions(limit)
893
+ results = self.find_most_complex_functions(limit, repo_path=repo_path)
895
894
  return {
896
895
  "query_type": "find_complexity", "limit": limit, "results": results,
897
896
  "summary": f"Found the top {len(results)} most complex functions"
898
897
  }
899
898
 
900
899
  elif query_type == "find_all_callers":
901
- results = self.find_all_callers(target, context)
900
+ results = self.find_all_callers(target, context, repo_path=repo_path)
902
901
  return {
903
902
  "query_type": "find_all_callers", "target": target, "context": context, "results": results,
904
903
  "summary": f"Found {len(results)} direct and indirect callers of '{target}'"
905
904
  }
906
905
 
907
906
  elif query_type == "find_all_callees":
908
- results = self.find_all_callees(target, context)
907
+ results = self.find_all_callees(target, context, repo_path=repo_path)
909
908
  return {
910
909
  "query_type": "find_all_callees", "target": target, "context": context, "results": results,
911
910
  "summary": f"Found {len(results)} direct and indirect callees of '{target}'"
@@ -916,7 +915,7 @@ class CodeFinder:
916
915
  start_func, end_func = target.split('->', 1)
917
916
  # max_depth can be passed as context, default to 5 if not provided or invalid
918
917
  max_depth = int(context) if context and context.isdigit() else 5
919
- results = self.find_function_call_chain(start_func.strip(), end_func.strip(), max_depth)
918
+ results = self.find_function_call_chain(start_func.strip(), end_func.strip(), max_depth, repo_path=repo_path)
920
919
  return {
921
920
  "query_type": "call_chain", "target": target, "results": results,
922
921
  "summary": f"Found {len(results)} call chains from '{start_func.strip()}' to '{end_func.strip()}' (max depth: {max_depth})"
@@ -928,14 +927,14 @@ class CodeFinder:
928
927
  }
929
928
 
930
929
  elif query_type in ["module_deps", "module_dependencies", "module_usage"]:
931
- results = self.find_module_dependencies(target)
930
+ results = self.find_module_dependencies(target, repo_path=repo_path)
932
931
  return {
933
932
  "query_type": "module_dependencies", "target": target, "results": results,
934
933
  "summary": f"Module '{target}' is imported by {len(results['imported_by_files'])} files"
935
934
  }
936
935
 
937
936
  elif query_type in ["variable_scope", "var_scope", "variable_usage_scope"]:
938
- results = self.find_variable_usage_scope(target)
937
+ results = self.find_variable_usage_scope(target, repo_path=repo_path)
939
938
  return {
940
939
  "query_type": "variable_scope", "target": target, "results": results,
941
940
  "summary": f"Variable '{target}' has {len(results['instances'])} instances across different scopes"