codegraphcontext 0.3.5__tar.gz → 0.3.8__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.
- {codegraphcontext-0.3.5/src/codegraphcontext.egg-info → codegraphcontext-0.3.8}/PKG-INFO +6 -5
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/README.md +3 -3
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/pyproject.toml +3 -2
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/cli_helpers.py +8 -6
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/setup_wizard.py +6 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/core/database_kuzu.py +20 -10
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/server.py +36 -1
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/code_finder.py +93 -31
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/graph_builder.py +88 -19
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/cpp.py +137 -72
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/go.py +42 -5
- codegraphcontext-0.3.8/src/codegraphcontext/utils/path_ignore.py +55 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/utils/tree_sitter_manager.py +8 -9
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8/src/codegraphcontext.egg-info}/PKG-INFO +6 -5
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext.egg-info/SOURCES.txt +1 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext.egg-info/requires.txt +2 -1
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/LICENSE +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/MANIFEST.in +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/setup.cfg +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/__init__.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/__main__.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/__init__.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/config_manager.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/main.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/registry_commands.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/setup_macos.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/visualizer.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/core/__init__.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/core/bundle_registry.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/core/cgc_bundle.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/core/database.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/core/database_falkordb.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/core/database_falkordb_remote.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/core/falkor_worker.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/core/jobs.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/core/watcher.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/prompts.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tool_definitions.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/__init__.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/advanced_language_query_tool.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/handlers/analysis_handlers.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/handlers/indexing_handlers.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/handlers/management_handlers.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/handlers/query_handlers.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/handlers/watcher_handlers.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/c.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/csharp.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/dart.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/elixir.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/haskell.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/java.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/javascript.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/kotlin.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/perl.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/php.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/python.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/ruby.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/rust.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/scala.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/swift.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/typescript.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/typescriptjsx.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/package_resolver.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/c_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/dart_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/go_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/haskell_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/java_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/perl_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/python_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/rust_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/scala_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/swift_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/scip_indexer.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/scip_pb2.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/system.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/utils/debug_log.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/utils/visualize_graph.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/viz/server.py +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext.egg-info/dependency_links.txt +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext.egg-info/entry_points.txt +0 -0
- {codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codegraphcontext
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.8
|
|
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
|
|
@@ -41,7 +41,7 @@ Requires-Dist: watchdog>=3.0.0
|
|
|
41
41
|
Requires-Dist: stdlibs>=2023.11.18
|
|
42
42
|
Requires-Dist: typer[all]>=0.9.0
|
|
43
43
|
Requires-Dist: rich>=13.7.0
|
|
44
|
-
Requires-Dist: inquirerpy>=0.3.
|
|
44
|
+
Requires-Dist: inquirerpy>=0.3.4
|
|
45
45
|
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
|
|
@@ -51,6 +51,7 @@ Requires-Dist: nbformat
|
|
|
51
51
|
Requires-Dist: nbconvert>=7.16.6
|
|
52
52
|
Requires-Dist: pathspec>=0.12.1
|
|
53
53
|
Requires-Dist: falkordb>=0.1.0
|
|
54
|
+
Requires-Dist: requests>=2.28.0
|
|
54
55
|
Requires-Dist: falkordblite>=0.1.0; sys_platform != "win32" and python_version >= "3.12"
|
|
55
56
|
Requires-Dist: fastapi>=0.100.0
|
|
56
57
|
Requires-Dist: uvicorn>=0.22.0
|
|
@@ -162,7 +163,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
|
|
|
162
163
|
---
|
|
163
164
|
|
|
164
165
|
## Project Details
|
|
165
|
-
- **Version:** 0.3.
|
|
166
|
+
- **Version:** 0.3.8
|
|
166
167
|
- **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
|
|
167
168
|
- **License:** MIT License (See [LICENSE](LICENSE) for details)
|
|
168
169
|
- **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
|
|
@@ -249,7 +250,7 @@ _If you’re using CodeGraphContext in your project, feel free to open a PR and
|
|
|
249
250
|
- `stdlibs>=2023.11.18`
|
|
250
251
|
- `typer[all]>=0.9.0`
|
|
251
252
|
- `rich>=13.7.0`
|
|
252
|
-
- `inquirerpy>=0.3.
|
|
253
|
+
- `inquirerpy>=0.3.7`
|
|
253
254
|
- `python-dotenv>=1.0.0`
|
|
254
255
|
- `tree-sitter>=0.21.0`
|
|
255
256
|
- `tree-sitter-language-pack>=0.6.0`
|
|
@@ -271,7 +272,7 @@ pip install codegraphcontext
|
|
|
271
272
|
|
|
272
273
|
### If 'cgc' command isn't found, run our one-line fix:
|
|
273
274
|
```
|
|
274
|
-
curl -sSL
|
|
275
|
+
curl -sSL https://raw.githubusercontent.com/CodeGraphContext/CodeGraphContext/main/scripts/post_install_fix.sh | bash
|
|
275
276
|
```
|
|
276
277
|
|
|
277
278
|
---
|
|
@@ -96,7 +96,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
|
|
|
96
96
|
---
|
|
97
97
|
|
|
98
98
|
## Project Details
|
|
99
|
-
- **Version:** 0.3.
|
|
99
|
+
- **Version:** 0.3.8
|
|
100
100
|
- **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
|
|
101
101
|
- **License:** MIT License (See [LICENSE](LICENSE) for details)
|
|
102
102
|
- **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
|
|
@@ -183,7 +183,7 @@ _If you’re using CodeGraphContext in your project, feel free to open a PR and
|
|
|
183
183
|
- `stdlibs>=2023.11.18`
|
|
184
184
|
- `typer[all]>=0.9.0`
|
|
185
185
|
- `rich>=13.7.0`
|
|
186
|
-
- `inquirerpy>=0.3.
|
|
186
|
+
- `inquirerpy>=0.3.7`
|
|
187
187
|
- `python-dotenv>=1.0.0`
|
|
188
188
|
- `tree-sitter>=0.21.0`
|
|
189
189
|
- `tree-sitter-language-pack>=0.6.0`
|
|
@@ -205,7 +205,7 @@ pip install codegraphcontext
|
|
|
205
205
|
|
|
206
206
|
### If 'cgc' command isn't found, run our one-line fix:
|
|
207
207
|
```
|
|
208
|
-
curl -sSL
|
|
208
|
+
curl -sSL https://raw.githubusercontent.com/CodeGraphContext/CodeGraphContext/main/scripts/post_install_fix.sh | bash
|
|
209
209
|
```
|
|
210
210
|
|
|
211
211
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "codegraphcontext"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.8"
|
|
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"
|
|
@@ -20,7 +20,7 @@ dependencies = [
|
|
|
20
20
|
"stdlibs>=2023.11.18",
|
|
21
21
|
"typer[all]>=0.9.0",
|
|
22
22
|
"rich>=13.7.0",
|
|
23
|
-
"inquirerpy>=0.3.
|
|
23
|
+
"inquirerpy>=0.3.4",
|
|
24
24
|
"python-dotenv>=1.0.0",
|
|
25
25
|
"tree-sitter>=0.21.0",
|
|
26
26
|
"tree-sitter-language-pack>=0.6.0",
|
|
@@ -30,6 +30,7 @@ dependencies = [
|
|
|
30
30
|
"nbconvert>=7.16.6",
|
|
31
31
|
"pathspec>=0.12.1",
|
|
32
32
|
"falkordb>=0.1.0",
|
|
33
|
+
"requests>=2.28.0",
|
|
33
34
|
"falkordblite>=0.1.0; sys_platform != 'win32' and python_version >= '3.12'",
|
|
34
35
|
"fastapi>=0.100.0",
|
|
35
36
|
"uvicorn>=0.22.0"
|
|
@@ -483,9 +483,10 @@ def clean_helper():
|
|
|
483
483
|
console.print("[cyan]🧹 Cleaning database (removing orphaned nodes)...[/cyan]")
|
|
484
484
|
|
|
485
485
|
try:
|
|
486
|
-
# Determine
|
|
486
|
+
# Determine backend type for query compatibility
|
|
487
487
|
db_type = db_manager.__class__.__name__
|
|
488
488
|
is_falkordb = "Falkor" in db_type
|
|
489
|
+
is_kuzu = "Kuzu" in db_type
|
|
489
490
|
|
|
490
491
|
total_deleted = 0
|
|
491
492
|
batch_size = 1000
|
|
@@ -493,14 +494,15 @@ def clean_helper():
|
|
|
493
494
|
with db_manager.get_driver().session() as session:
|
|
494
495
|
# Keep deleting orphaned nodes in batches until none are found
|
|
495
496
|
while True:
|
|
496
|
-
if is_falkordb:
|
|
497
|
-
# FalkorDB-compatible query using OPTIONAL MATCH
|
|
497
|
+
if is_falkordb or is_kuzu:
|
|
498
|
+
# FalkorDB / KùzuDB-compatible query using OPTIONAL MATCH
|
|
499
|
+
# (KùzuDB does not support the Neo4j `NOT EXISTS { MATCH ... }` subquery syntax)
|
|
498
500
|
query = """
|
|
499
501
|
MATCH (n)
|
|
500
502
|
WHERE NOT (n:Repository)
|
|
501
|
-
OPTIONAL MATCH
|
|
502
|
-
WITH n,
|
|
503
|
-
WHERE
|
|
503
|
+
OPTIONAL MATCH p = (n)-[*..10]-(r:Repository)
|
|
504
|
+
WITH n, p
|
|
505
|
+
WHERE p IS NULL
|
|
504
506
|
WITH n LIMIT $batch_size
|
|
505
507
|
DETACH DELETE n
|
|
506
508
|
RETURN count(n) as deleted
|
|
@@ -296,6 +296,12 @@ def run_command(command, console, shell=False, check=True, input_text=None):
|
|
|
296
296
|
Returns the completed process object on success, None on failure.
|
|
297
297
|
"""
|
|
298
298
|
cmd_str = command if isinstance(command, str) else ' '.join(command)
|
|
299
|
+
|
|
300
|
+
# Mask passwords from being printed out
|
|
301
|
+
if "set-initial-password" in cmd_str:
|
|
302
|
+
import re
|
|
303
|
+
cmd_str = re.sub(r'(set-initial-password\s+)(\S+)', r'\g<1>********', cmd_str)
|
|
304
|
+
|
|
299
305
|
console.print(f"[cyan]$ {cmd_str}[/cyan]")
|
|
300
306
|
try:
|
|
301
307
|
process = subprocess.run(
|
{codegraphcontext-0.3.5 → codegraphcontext-0.3.8}/src/codegraphcontext/core/database_kuzu.py
RENAMED
|
@@ -109,14 +109,21 @@ class KuzuDBManager:
|
|
|
109
109
|
("Parameter", "uid STRING, name STRING, path STRING, function_line_number INT64, PRIMARY KEY (uid)")
|
|
110
110
|
]
|
|
111
111
|
|
|
112
|
+
# rel_tables: list of (table_name, schema, use_group)
|
|
113
|
+
# use_group=True -> CREATE REL TABLE GROUP (for multi FROM..TO bindings)
|
|
114
|
+
# use_group=False -> CREATE REL TABLE (single binding)
|
|
112
115
|
rel_tables = [
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
("
|
|
118
|
-
("
|
|
119
|
-
("
|
|
116
|
+
# Note: in KùzuDB, some labels (e.g. `Macro`, `Property`, `Union`) are treated as reserved
|
|
117
|
+
# keywords in CREATE REL TABLE statements. We must escape them with backticks
|
|
118
|
+
# or the rel table creation will fail silently, leading to runtime
|
|
119
|
+
# "Binder exception: Table CONTAINS does not exist".
|
|
120
|
+
("CONTAINS", "FROM File TO Function, FROM File TO Class, FROM File TO Variable, FROM File TO Trait, FROM File TO Interface, FROM `Macro` TO `Macro`, FROM File TO `Macro`, FROM File TO Struct, FROM File TO Enum, FROM File TO `Union`, FROM File TO Annotation, FROM File TO Record, FROM File TO `Property`, FROM Repository TO Directory, FROM Directory TO Directory, FROM Directory TO File, FROM Repository TO File, FROM Class TO Function, FROM Function TO Function", True),
|
|
121
|
+
("CALLS", "FROM Function TO Function, FROM Function TO Class, FROM File TO Function, FROM File TO Class, FROM Class TO Function, FROM Class TO Class, line_number INT64, args STRING[], full_call_name STRING", True),
|
|
122
|
+
("IMPORTS", "FROM File TO Module, alias STRING, full_import_name STRING, imported_name STRING, line_number INT64", False),
|
|
123
|
+
("INHERITS", "FROM Class TO Class, FROM Record TO Record, FROM Interface TO Interface", True),
|
|
124
|
+
("HAS_PARAMETER", "FROM Function TO Parameter", False),
|
|
125
|
+
("INCLUDES", "FROM Class TO Module", False),
|
|
126
|
+
("IMPLEMENTS", "FROM Class TO Interface, FROM Struct TO Interface, FROM Record TO Interface", True)
|
|
120
127
|
]
|
|
121
128
|
|
|
122
129
|
for table_name, schema in node_tables:
|
|
@@ -127,10 +134,13 @@ class KuzuDBManager:
|
|
|
127
134
|
warning_logger(f"Kuzu Schema Node Error ({table_name}): {e}")
|
|
128
135
|
debug_log(f"Kuzu Schema Node Error ({table_name}): {e}")
|
|
129
136
|
|
|
130
|
-
for table_name, schema in rel_tables:
|
|
137
|
+
for table_name, schema, use_group in rel_tables:
|
|
131
138
|
try:
|
|
132
|
-
|
|
133
|
-
|
|
139
|
+
if use_group:
|
|
140
|
+
# KùzuDB requires CREATE REL TABLE GROUP for multi-binding relationships
|
|
141
|
+
self._conn.execute(f"CREATE REL TABLE GROUP `{table_name}`({schema})")
|
|
142
|
+
else:
|
|
143
|
+
self._conn.execute(f"CREATE REL TABLE `{table_name}`({schema})")
|
|
134
144
|
except Exception as e:
|
|
135
145
|
if "already exists" not in str(e).lower():
|
|
136
146
|
warning_logger(f"Kuzu Schema Rel Error ({table_name}): {e}")
|
|
@@ -36,6 +36,40 @@ from .tools.handlers import (
|
|
|
36
36
|
DEFAULT_EDIT_DISTANCE = 2
|
|
37
37
|
DEFAULT_FUZZY_SEARCH = False
|
|
38
38
|
|
|
39
|
+
WORKSPACE_PREFIX = "/workspace/"
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _is_path_key(key: str) -> bool:
|
|
43
|
+
"""Check if a dict key represents a file path field.
|
|
44
|
+
|
|
45
|
+
Matches keys like 'path', 'clone_path', 'caller_file_path', and also
|
|
46
|
+
Cypher-aliased keys like 'f.path', 'n.caller_file_path'.
|
|
47
|
+
"""
|
|
48
|
+
# Strip Cypher alias prefix (e.g. "f.path" -> "path")
|
|
49
|
+
bare = key.rsplit(".", 1)[-1] if "." in key else key
|
|
50
|
+
return bare == "path" or bare.endswith("_path")
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
def _strip_path_value(value):
|
|
54
|
+
"""Strip /workspace/ prefix from a single string value."""
|
|
55
|
+
if isinstance(value, str) and value.startswith(WORKSPACE_PREFIX):
|
|
56
|
+
return value[len(WORKSPACE_PREFIX):]
|
|
57
|
+
return value
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def _strip_workspace_prefix(obj):
|
|
61
|
+
"""Recursively strip /workspace/ prefix from path values in results."""
|
|
62
|
+
if isinstance(obj, dict):
|
|
63
|
+
return {
|
|
64
|
+
k: _strip_path_value(v) if _is_path_key(k) else _strip_workspace_prefix(v)
|
|
65
|
+
for k, v in obj.items()
|
|
66
|
+
}
|
|
67
|
+
elif isinstance(obj, list):
|
|
68
|
+
return [_strip_workspace_prefix(item) for item in obj]
|
|
69
|
+
return obj
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
39
73
|
class MCPServer:
|
|
40
74
|
"""
|
|
41
75
|
The main MCP Server class.
|
|
@@ -254,7 +288,8 @@ class MCPServer:
|
|
|
254
288
|
tool_name = params.get('name')
|
|
255
289
|
args = params.get('arguments', {})
|
|
256
290
|
result = await self.handle_tool_call(tool_name, args)
|
|
257
|
-
|
|
291
|
+
result = _strip_workspace_prefix(result)
|
|
292
|
+
|
|
258
293
|
if "error" in result:
|
|
259
294
|
response = {
|
|
260
295
|
"jsonrpc": "2.0", "id": request_id,
|
|
@@ -5,6 +5,7 @@ from typing import Any, Dict, List, Literal, Optional
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
|
|
7
7
|
from ..core.database import DatabaseManager
|
|
8
|
+
from ..utils.path_ignore import cypher_path_not_under_ignore_dirs
|
|
8
9
|
|
|
9
10
|
logger = logging.getLogger(__name__)
|
|
10
11
|
|
|
@@ -539,9 +540,13 @@ class CodeFinder:
|
|
|
539
540
|
|
|
540
541
|
with self.driver.session() as session:
|
|
541
542
|
repo_filter = "AND func.path STARTS WITH $repo_path" if repo_path else ""
|
|
542
|
-
|
|
543
|
+
decorator_filter = "AND ALL(decorator_name IN $exclude_decorated_with WHERE NOT decorator_name IN func.decorators)" if exclude_decorated_with else ""
|
|
544
|
+
func_ignore = cypher_path_not_under_ignore_dirs("func.path")
|
|
545
|
+
caller_ignore = cypher_path_not_under_ignore_dirs("caller.path")
|
|
546
|
+
|
|
547
|
+
query = f"""
|
|
543
548
|
MATCH (func:Function)
|
|
544
|
-
WHERE func.is_dependency = false {repo_filter}
|
|
549
|
+
WHERE func.is_dependency = false {repo_filter} {func_ignore}
|
|
545
550
|
AND NOT func.name IN ['main', 'setup', 'run']
|
|
546
551
|
AND NOT (func.name STARTS WITH '__' AND func.name ENDS WITH '__')
|
|
547
552
|
AND NOT func.name STARTS WITH '_test'
|
|
@@ -550,10 +555,10 @@ class CodeFinder:
|
|
|
550
555
|
AND NOT toLower(func.name) CONTAINS 'application'
|
|
551
556
|
AND NOT toLower(func.name) CONTAINS 'entry'
|
|
552
557
|
AND NOT toLower(func.name) CONTAINS 'entrypoint'
|
|
553
|
-
|
|
558
|
+
{decorator_filter}
|
|
554
559
|
WITH func
|
|
555
560
|
OPTIONAL MATCH (caller:Function)-[:CALLS]->(func)
|
|
556
|
-
WHERE caller.is_dependency = false
|
|
561
|
+
WHERE caller.is_dependency = false {caller_ignore}
|
|
557
562
|
WITH func, count(caller) as caller_count
|
|
558
563
|
WHERE caller_count = 0
|
|
559
564
|
OPTIONAL MATCH (file:File)-[:CONTAINS]->(func)
|
|
@@ -566,7 +571,15 @@ class CodeFinder:
|
|
|
566
571
|
file.name as file_name
|
|
567
572
|
ORDER BY func.path, func.line_number
|
|
568
573
|
LIMIT 50
|
|
569
|
-
"""
|
|
574
|
+
"""
|
|
575
|
+
|
|
576
|
+
params = {}
|
|
577
|
+
if repo_path:
|
|
578
|
+
params["repo_path"] = repo_path
|
|
579
|
+
if exclude_decorated_with:
|
|
580
|
+
params["exclude_decorated_with"] = exclude_decorated_with
|
|
581
|
+
|
|
582
|
+
result = session.run(query, **params)
|
|
570
583
|
|
|
571
584
|
return {
|
|
572
585
|
"potentially_unused_functions": result.data(),
|
|
@@ -581,8 +594,8 @@ class CodeFinder:
|
|
|
581
594
|
# KùzuDB-compatible: Use anonymous end node and filter with WHERE
|
|
582
595
|
query = f"""
|
|
583
596
|
MATCH p = (f:Function)-[:CALLS*]->()
|
|
584
|
-
WITH f, p, nodes(p) as path_nodes
|
|
585
|
-
WITH f, path_nodes
|
|
597
|
+
WITH f as f, p as p, nodes(p) as path_nodes
|
|
598
|
+
WITH f as f, path_nodes as path_nodes, path_nodes[size(path_nodes)] as target
|
|
586
599
|
WHERE target.name = $function_name AND target.path = $path {repo_filter}
|
|
587
600
|
RETURN DISTINCT f.name AS caller_name, f.path AS caller_file_path, f.line_number AS caller_line_number, f.is_dependency AS caller_is_dependency
|
|
588
601
|
ORDER BY caller_is_dependency ASC, caller_file_path, caller_line_number
|
|
@@ -593,8 +606,8 @@ class CodeFinder:
|
|
|
593
606
|
# KùzuDB-compatible: Use anonymous end node and filter with WHERE
|
|
594
607
|
query = f"""
|
|
595
608
|
MATCH p = (f:Function)-[:CALLS*]->()
|
|
596
|
-
WITH f, p, nodes(p) as path_nodes
|
|
597
|
-
WITH f, path_nodes
|
|
609
|
+
WITH f as f, p as p, nodes(p) as path_nodes
|
|
610
|
+
WITH f as f, path_nodes as path_nodes, path_nodes[size(path_nodes)] as target
|
|
598
611
|
WHERE target.name = $function_name {repo_filter}
|
|
599
612
|
RETURN DISTINCT f.name AS caller_name, f.path AS caller_file_path, f.line_number AS caller_line_number, f.is_dependency AS caller_is_dependency
|
|
600
613
|
ORDER BY caller_is_dependency ASC, caller_file_path, caller_line_number
|
|
@@ -612,8 +625,8 @@ class CodeFinder:
|
|
|
612
625
|
query = f"""
|
|
613
626
|
MATCH (caller:Function {{name: $function_name, path: $path}})
|
|
614
627
|
MATCH p = (caller)-[:CALLS*]->()
|
|
615
|
-
WITH p, nodes(p) as path_nodes
|
|
616
|
-
WITH
|
|
628
|
+
WITH p as p, nodes(p) as path_nodes
|
|
629
|
+
WITH path_nodes[size(path_nodes)] as f
|
|
617
630
|
{repo_filter}
|
|
618
631
|
RETURN DISTINCT f.name AS callee_name, f.path AS callee_file_path, f.line_number AS callee_line_number, f.is_dependency AS callee_is_dependency
|
|
619
632
|
ORDER BY callee_is_dependency ASC, callee_file_path, callee_line_number
|
|
@@ -625,8 +638,8 @@ class CodeFinder:
|
|
|
625
638
|
query = f"""
|
|
626
639
|
MATCH (caller:Function {{name: $function_name}})
|
|
627
640
|
MATCH p = (caller)-[:CALLS*]->()
|
|
628
|
-
WITH p, nodes(p) as path_nodes
|
|
629
|
-
WITH
|
|
641
|
+
WITH p as p, nodes(p) as path_nodes
|
|
642
|
+
WITH path_nodes[size(path_nodes)] as f
|
|
630
643
|
{repo_filter}
|
|
631
644
|
RETURN DISTINCT f.name AS callee_name, f.path AS callee_file_path, f.line_number AS callee_line_number, f.is_dependency AS callee_is_dependency
|
|
632
645
|
ORDER BY callee_is_dependency ASC, callee_file_path, callee_line_number
|
|
@@ -647,24 +660,12 @@ class CodeFinder:
|
|
|
647
660
|
query = f"""
|
|
648
661
|
MATCH (start:Function {start_props}), (end_target:Function {end_props})
|
|
649
662
|
{repo_filter}
|
|
650
|
-
WITH start, end_target
|
|
663
|
+
WITH start as start, end_target as end_target
|
|
651
664
|
MATCH path = (start)-[:CALLS*1..{max_depth}]->()
|
|
652
|
-
WITH path, end_target, nodes(path) as func_nodes, relationships(path) as call_rels
|
|
653
|
-
WITH path, func_nodes, call_rels,
|
|
665
|
+
WITH path as path, end_target as end_target, nodes(path) as func_nodes, relationships(path) as call_rels
|
|
666
|
+
WITH path as path, func_nodes as func_nodes, call_rels as call_rels, end_target as end_target, func_nodes[size(func_nodes)] as path_end
|
|
654
667
|
WHERE path_end.name = end_target.name AND (end_target.path IS NULL OR path_end.path = end_target.path)
|
|
655
|
-
RETURN
|
|
656
|
-
[node in func_nodes | {{
|
|
657
|
-
name: node.name,
|
|
658
|
-
path: node.path,
|
|
659
|
-
line_number: node.line_number,
|
|
660
|
-
is_dependency: node.is_dependency
|
|
661
|
-
}}] as function_chain,
|
|
662
|
-
[rel in call_rels | {{
|
|
663
|
-
call_line: rel.line_number,
|
|
664
|
-
args: rel.args,
|
|
665
|
-
full_call_name: rel.full_call_name
|
|
666
|
-
}}] as call_details,
|
|
667
|
-
length(path) as chain_length
|
|
668
|
+
RETURN func_nodes as function_nodes, call_rels as call_nodes, size(call_rels) as chain_length
|
|
668
669
|
ORDER BY chain_length ASC
|
|
669
670
|
LIMIT 20
|
|
670
671
|
"""
|
|
@@ -679,7 +680,67 @@ class CodeFinder:
|
|
|
679
680
|
}
|
|
680
681
|
|
|
681
682
|
result = session.run(query, **params)
|
|
682
|
-
|
|
683
|
+
|
|
684
|
+
# Post-process Node/Rel objects into plain dicts so CLI output stays stable
|
|
685
|
+
rows = result.data()
|
|
686
|
+
transformed: List[Dict[str, Any]] = []
|
|
687
|
+
for row in rows:
|
|
688
|
+
func_nodes = row.get("function_nodes") or []
|
|
689
|
+
rel_nodes = row.get("call_nodes") or []
|
|
690
|
+
chain_len = row.get("chain_length", 0)
|
|
691
|
+
|
|
692
|
+
function_chain = []
|
|
693
|
+
for n in func_nodes:
|
|
694
|
+
# Depending on KùzuDB + driver wrapping, list elements can arrive
|
|
695
|
+
# either as Node/Rel objects or already-materialized dicts.
|
|
696
|
+
if isinstance(n, dict):
|
|
697
|
+
props = n
|
|
698
|
+
else:
|
|
699
|
+
props = None
|
|
700
|
+
try:
|
|
701
|
+
props = n.get_properties()
|
|
702
|
+
except Exception:
|
|
703
|
+
props = getattr(n, "properties", None)
|
|
704
|
+
if props is None:
|
|
705
|
+
props = {}
|
|
706
|
+
function_chain.append(
|
|
707
|
+
{
|
|
708
|
+
"name": props.get("name"),
|
|
709
|
+
"path": props.get("path"),
|
|
710
|
+
"line_number": props.get("line_number"),
|
|
711
|
+
"is_dependency": props.get("is_dependency"),
|
|
712
|
+
}
|
|
713
|
+
)
|
|
714
|
+
|
|
715
|
+
call_details = []
|
|
716
|
+
for r in rel_nodes:
|
|
717
|
+
if isinstance(r, dict):
|
|
718
|
+
props = r
|
|
719
|
+
else:
|
|
720
|
+
props = None
|
|
721
|
+
try:
|
|
722
|
+
props = r.get_properties()
|
|
723
|
+
except Exception:
|
|
724
|
+
props = getattr(r, "properties", None)
|
|
725
|
+
if props is None:
|
|
726
|
+
props = {}
|
|
727
|
+
call_details.append(
|
|
728
|
+
{
|
|
729
|
+
"call_line": props.get("line_number"),
|
|
730
|
+
"args": props.get("args"),
|
|
731
|
+
"full_call_name": props.get("full_call_name"),
|
|
732
|
+
}
|
|
733
|
+
)
|
|
734
|
+
|
|
735
|
+
transformed.append(
|
|
736
|
+
{
|
|
737
|
+
"function_chain": function_chain,
|
|
738
|
+
"call_details": call_details,
|
|
739
|
+
"chain_length": chain_len,
|
|
740
|
+
}
|
|
741
|
+
)
|
|
742
|
+
|
|
743
|
+
return transformed
|
|
683
744
|
|
|
684
745
|
def find_by_type(self, element_type: str, limit: int = 50) -> List[Dict]:
|
|
685
746
|
"""Find all elements of a specific type (Function, Class, File, Module)."""
|
|
@@ -988,9 +1049,10 @@ class CodeFinder:
|
|
|
988
1049
|
"""Find the most complex functions based on cyclomatic complexity."""
|
|
989
1050
|
with self.driver.session() as session:
|
|
990
1051
|
repo_filter = "AND f.path STARTS WITH $repo_path" if repo_path else ""
|
|
1052
|
+
path_ignore = cypher_path_not_under_ignore_dirs("f.path")
|
|
991
1053
|
query = f"""
|
|
992
1054
|
MATCH (f:Function)
|
|
993
|
-
WHERE f.cyclomatic_complexity IS NOT NULL AND f.is_dependency = false {repo_filter}
|
|
1055
|
+
WHERE f.cyclomatic_complexity IS NOT NULL AND f.is_dependency = false {repo_filter} {path_ignore}
|
|
994
1056
|
RETURN f.name as function_name, f.path as path, f.cyclomatic_complexity as complexity, f.line_number as line_number
|
|
995
1057
|
ORDER BY f.cyclomatic_complexity DESC
|
|
996
1058
|
LIMIT $limit
|