codegraphcontext 0.3.7__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.7/src/codegraphcontext.egg-info → codegraphcontext-0.3.8}/PKG-INFO +4 -3
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/README.md +2 -2
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/pyproject.toml +2 -1
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/cli_helpers.py +8 -6
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/core/database_kuzu.py +20 -10
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/server.py +36 -1
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/code_finder.py +80 -28
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/graph_builder.py +88 -19
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/cpp.py +137 -72
- {codegraphcontext-0.3.7 → 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.7 → codegraphcontext-0.3.8}/src/codegraphcontext/utils/tree_sitter_manager.py +8 -9
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8/src/codegraphcontext.egg-info}/PKG-INFO +4 -3
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext.egg-info/SOURCES.txt +1 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext.egg-info/requires.txt +1 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/LICENSE +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/MANIFEST.in +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/setup.cfg +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/__init__.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/__main__.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/__init__.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/config_manager.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/main.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/registry_commands.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/setup_macos.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/setup_wizard.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/cli/visualizer.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/core/__init__.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/core/bundle_registry.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/core/cgc_bundle.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/core/database.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/core/database_falkordb.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/core/database_falkordb_remote.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/core/falkor_worker.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/core/jobs.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/core/watcher.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/prompts.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tool_definitions.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/__init__.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/advanced_language_query_tool.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/handlers/analysis_handlers.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/handlers/indexing_handlers.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/handlers/management_handlers.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/handlers/query_handlers.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/handlers/watcher_handlers.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/c.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/csharp.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/dart.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/elixir.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/haskell.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/java.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/javascript.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/kotlin.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/perl.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/php.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/python.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/ruby.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/rust.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/scala.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/swift.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/typescript.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/languages/typescriptjsx.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/package_resolver.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/c_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/dart_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/go_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/haskell_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/java_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/perl_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/python_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/rust_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/scala_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/swift_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/scip_indexer.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/scip_pb2.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/system.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/utils/debug_log.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/utils/visualize_graph.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/viz/server.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext.egg-info/dependency_links.txt +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext.egg-info/entry_points.txt +0 -0
- {codegraphcontext-0.3.7 → 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
|
|
@@ -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/)
|
|
@@ -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/)
|
|
@@ -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"
|
|
@@ -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
|
{codegraphcontext-0.3.7 → 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
|
|
|
@@ -540,10 +541,12 @@ class CodeFinder:
|
|
|
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")
|
|
543
546
|
|
|
544
547
|
query = f"""
|
|
545
548
|
MATCH (func:Function)
|
|
546
|
-
WHERE func.is_dependency = false {repo_filter}
|
|
549
|
+
WHERE func.is_dependency = false {repo_filter} {func_ignore}
|
|
547
550
|
AND NOT func.name IN ['main', 'setup', 'run']
|
|
548
551
|
AND NOT (func.name STARTS WITH '__' AND func.name ENDS WITH '__')
|
|
549
552
|
AND NOT func.name STARTS WITH '_test'
|
|
@@ -555,7 +558,7 @@ class CodeFinder:
|
|
|
555
558
|
{decorator_filter}
|
|
556
559
|
WITH func
|
|
557
560
|
OPTIONAL MATCH (caller:Function)-[:CALLS]->(func)
|
|
558
|
-
WHERE caller.is_dependency = false
|
|
561
|
+
WHERE caller.is_dependency = false {caller_ignore}
|
|
559
562
|
WITH func, count(caller) as caller_count
|
|
560
563
|
WHERE caller_count = 0
|
|
561
564
|
OPTIONAL MATCH (file:File)-[:CONTAINS]->(func)
|
|
@@ -591,8 +594,8 @@ class CodeFinder:
|
|
|
591
594
|
# KùzuDB-compatible: Use anonymous end node and filter with WHERE
|
|
592
595
|
query = f"""
|
|
593
596
|
MATCH p = (f:Function)-[:CALLS*]->()
|
|
594
|
-
WITH f, p, nodes(p) as path_nodes
|
|
595
|
-
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
|
|
596
599
|
WHERE target.name = $function_name AND target.path = $path {repo_filter}
|
|
597
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
|
|
598
601
|
ORDER BY caller_is_dependency ASC, caller_file_path, caller_line_number
|
|
@@ -603,8 +606,8 @@ class CodeFinder:
|
|
|
603
606
|
# KùzuDB-compatible: Use anonymous end node and filter with WHERE
|
|
604
607
|
query = f"""
|
|
605
608
|
MATCH p = (f:Function)-[:CALLS*]->()
|
|
606
|
-
WITH f, p, nodes(p) as path_nodes
|
|
607
|
-
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
|
|
608
611
|
WHERE target.name = $function_name {repo_filter}
|
|
609
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
|
|
610
613
|
ORDER BY caller_is_dependency ASC, caller_file_path, caller_line_number
|
|
@@ -622,8 +625,8 @@ class CodeFinder:
|
|
|
622
625
|
query = f"""
|
|
623
626
|
MATCH (caller:Function {{name: $function_name, path: $path}})
|
|
624
627
|
MATCH p = (caller)-[:CALLS*]->()
|
|
625
|
-
WITH p, nodes(p) as path_nodes
|
|
626
|
-
WITH
|
|
628
|
+
WITH p as p, nodes(p) as path_nodes
|
|
629
|
+
WITH path_nodes[size(path_nodes)] as f
|
|
627
630
|
{repo_filter}
|
|
628
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
|
|
629
632
|
ORDER BY callee_is_dependency ASC, callee_file_path, callee_line_number
|
|
@@ -635,8 +638,8 @@ class CodeFinder:
|
|
|
635
638
|
query = f"""
|
|
636
639
|
MATCH (caller:Function {{name: $function_name}})
|
|
637
640
|
MATCH p = (caller)-[:CALLS*]->()
|
|
638
|
-
WITH p, nodes(p) as path_nodes
|
|
639
|
-
WITH
|
|
641
|
+
WITH p as p, nodes(p) as path_nodes
|
|
642
|
+
WITH path_nodes[size(path_nodes)] as f
|
|
640
643
|
{repo_filter}
|
|
641
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
|
|
642
645
|
ORDER BY callee_is_dependency ASC, callee_file_path, callee_line_number
|
|
@@ -657,24 +660,12 @@ class CodeFinder:
|
|
|
657
660
|
query = f"""
|
|
658
661
|
MATCH (start:Function {start_props}), (end_target:Function {end_props})
|
|
659
662
|
{repo_filter}
|
|
660
|
-
WITH start, end_target
|
|
663
|
+
WITH start as start, end_target as end_target
|
|
661
664
|
MATCH path = (start)-[:CALLS*1..{max_depth}]->()
|
|
662
|
-
WITH path, end_target, nodes(path) as func_nodes, relationships(path) as call_rels
|
|
663
|
-
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
|
|
664
667
|
WHERE path_end.name = end_target.name AND (end_target.path IS NULL OR path_end.path = end_target.path)
|
|
665
|
-
RETURN
|
|
666
|
-
[node in func_nodes | {{
|
|
667
|
-
name: node.name,
|
|
668
|
-
path: node.path,
|
|
669
|
-
line_number: node.line_number,
|
|
670
|
-
is_dependency: node.is_dependency
|
|
671
|
-
}}] as function_chain,
|
|
672
|
-
[rel in call_rels | {{
|
|
673
|
-
call_line: rel.line_number,
|
|
674
|
-
args: rel.args,
|
|
675
|
-
full_call_name: rel.full_call_name
|
|
676
|
-
}}] as call_details,
|
|
677
|
-
length(path) as chain_length
|
|
668
|
+
RETURN func_nodes as function_nodes, call_rels as call_nodes, size(call_rels) as chain_length
|
|
678
669
|
ORDER BY chain_length ASC
|
|
679
670
|
LIMIT 20
|
|
680
671
|
"""
|
|
@@ -689,7 +680,67 @@ class CodeFinder:
|
|
|
689
680
|
}
|
|
690
681
|
|
|
691
682
|
result = session.run(query, **params)
|
|
692
|
-
|
|
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
|
|
693
744
|
|
|
694
745
|
def find_by_type(self, element_type: str, limit: int = 50) -> List[Dict]:
|
|
695
746
|
"""Find all elements of a specific type (Function, Class, File, Module)."""
|
|
@@ -998,9 +1049,10 @@ class CodeFinder:
|
|
|
998
1049
|
"""Find the most complex functions based on cyclomatic complexity."""
|
|
999
1050
|
with self.driver.session() as session:
|
|
1000
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")
|
|
1001
1053
|
query = f"""
|
|
1002
1054
|
MATCH (f:Function)
|
|
1003
|
-
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}
|
|
1004
1056
|
RETURN f.name as function_name, f.path as path, f.cyclomatic_complexity as complexity, f.line_number as line_number
|
|
1005
1057
|
ORDER BY f.cyclomatic_complexity DESC
|
|
1006
1058
|
LIMIT $limit
|
{codegraphcontext-0.3.7 → codegraphcontext-0.3.8}/src/codegraphcontext/tools/graph_builder.py
RENAMED
|
@@ -14,9 +14,22 @@ from ..utils.debug_log import debug_log, info_logger, error_logger, warning_logg
|
|
|
14
14
|
from tree_sitter import Language, Parser
|
|
15
15
|
from ..utils.tree_sitter_manager import get_tree_sitter_manager
|
|
16
16
|
from ..cli.config_manager import get_config_value
|
|
17
|
+
from ..utils.path_ignore import file_path_has_ignore_dir_segment
|
|
17
18
|
import fnmatch
|
|
18
19
|
|
|
19
20
|
DEFAULT_IGNORE_PATTERNS = [
|
|
21
|
+
# Vendor / env dirs (gitignore-style; complements IGNORE_DIRS during indexing)
|
|
22
|
+
"node_modules/",
|
|
23
|
+
"venv/",
|
|
24
|
+
".venv/",
|
|
25
|
+
"env/",
|
|
26
|
+
".env/",
|
|
27
|
+
"dist/",
|
|
28
|
+
"build/",
|
|
29
|
+
"target/",
|
|
30
|
+
"out/",
|
|
31
|
+
".git/",
|
|
32
|
+
"__pycache__/",
|
|
20
33
|
"*.png",
|
|
21
34
|
"*.jpg",
|
|
22
35
|
"*.jpeg",
|
|
@@ -210,6 +223,12 @@ class GraphBuilder:
|
|
|
210
223
|
except Exception as e:
|
|
211
224
|
warning_logger(f"Schema creation warning: {e}")
|
|
212
225
|
|
|
226
|
+
# Neo4j RANGE indexes have an ~8 kB key-size limit. Long C++ template
|
|
227
|
+
# function names (e.g. from llama.cpp) can exceed this, causing
|
|
228
|
+
# "Property value is too large to index" errors. We cap string properties
|
|
229
|
+
# at 4096 chars, which is comfortably under the 8 kB boundary.
|
|
230
|
+
_MAX_STR_LEN = 4096
|
|
231
|
+
|
|
213
232
|
@staticmethod
|
|
214
233
|
def _sanitize_props(props: Dict) -> Dict:
|
|
215
234
|
"""Return a copy of *props* with all values coerced to database-safe types.
|
|
@@ -220,9 +239,15 @@ class GraphBuilder:
|
|
|
220
239
|
parsers (e.g. C's ``detailed_args`` or Scala's tuple ``class_context``)
|
|
221
240
|
are serialized to a JSON string so the data is preserved rather than
|
|
222
241
|
being silently dropped.
|
|
242
|
+
|
|
243
|
+
Additionally, string values are truncated to _MAX_STR_LEN characters to
|
|
244
|
+
avoid Neo4j's RANGE-index 8 kB property-size limit (triggered by very
|
|
245
|
+
long C++ template-mangled function names).
|
|
223
246
|
"""
|
|
224
247
|
import json
|
|
225
248
|
|
|
249
|
+
MAX = GraphBuilder._MAX_STR_LEN
|
|
250
|
+
|
|
226
251
|
def _is_primitive(v):
|
|
227
252
|
return isinstance(v, (str, int, float, bool)) or v is None
|
|
228
253
|
|
|
@@ -230,15 +255,21 @@ class GraphBuilder:
|
|
|
230
255
|
return isinstance(v, list) and all(_is_primitive(item) for item in v)
|
|
231
256
|
|
|
232
257
|
def _coerce(v):
|
|
258
|
+
if isinstance(v, str):
|
|
259
|
+
# Truncate long strings to stay within Neo4j RANGE index limits
|
|
260
|
+
return v[:MAX] if len(v) > MAX else v
|
|
233
261
|
if _is_primitive(v):
|
|
234
262
|
return v
|
|
235
263
|
if _is_flat_list(v):
|
|
236
|
-
|
|
264
|
+
# Truncate any long strings in lists too
|
|
265
|
+
return [s[:MAX] if isinstance(s, str) and len(s) > MAX else s for s in v]
|
|
237
266
|
# Tuples, dicts, lists-of-dicts, nested structures → JSON string
|
|
238
267
|
try:
|
|
239
|
-
|
|
268
|
+
serialized = json.dumps(v, default=str)
|
|
269
|
+
return serialized[:MAX] if len(serialized) > MAX else serialized
|
|
240
270
|
except Exception:
|
|
241
|
-
|
|
271
|
+
s = str(v)
|
|
272
|
+
return s[:MAX] if len(s) > MAX else s
|
|
242
273
|
|
|
243
274
|
return {k: _coerce(v) for k, v in props.items()}
|
|
244
275
|
|
|
@@ -446,8 +477,20 @@ class GraphBuilder:
|
|
|
446
477
|
# before writing to the database to avoid runtime errors such as
|
|
447
478
|
# "Property values can only be of primitive types or arrays of
|
|
448
479
|
# primitive types" raised by FalkorDB / KùzuDB.
|
|
480
|
+
# _sanitize_props also truncates long strings to avoid Neo4j's
|
|
481
|
+
# 8 kB RANGE-index limit (seen with long C++ template names).
|
|
449
482
|
safe_props = self._sanitize_props(item)
|
|
450
|
-
|
|
483
|
+
try:
|
|
484
|
+
session.run(query, path=file_path_str, name=item['name'], line_number=item['line_number'], props=safe_props)
|
|
485
|
+
except Exception as node_err:
|
|
486
|
+
err_str = str(node_err)
|
|
487
|
+
if "too large to index" in err_str or "property size" in err_str.lower():
|
|
488
|
+
warning_logger(
|
|
489
|
+
f"Skipping {label} '{item['name']}' in {file_path_str}: "
|
|
490
|
+
f"property value too large for index (name length={len(item['name'])})"
|
|
491
|
+
)
|
|
492
|
+
else:
|
|
493
|
+
raise # Re-raise unexpected errors
|
|
451
494
|
|
|
452
495
|
if label == 'Function':
|
|
453
496
|
for arg_name in item.get('args', []):
|
|
@@ -517,30 +560,51 @@ class GraphBuilder:
|
|
|
517
560
|
# Ensure full_import_name is available in params for SET clause
|
|
518
561
|
params = imp.copy()
|
|
519
562
|
params['path'] = file_path_str
|
|
520
|
-
params['rel_props'] = rel_props
|
|
521
563
|
params['module_name'] = imp.get('name') # Use 'name' from imp as module name
|
|
522
564
|
|
|
565
|
+
# Sanitize scalar params but keep rel_props as a dict
|
|
566
|
+
# (FalkorDB SET r += $rel_props requires a map, not a string)
|
|
567
|
+
sanitized = self._sanitize_props(params)
|
|
568
|
+
sanitized['rel_props'] = rel_props
|
|
569
|
+
|
|
523
570
|
session.run(f"""
|
|
524
571
|
MATCH (f:File {{path: $path}})
|
|
525
572
|
MERGE (m:Module {{name: $module_name}})
|
|
526
573
|
{set_clause_str}
|
|
527
574
|
MERGE (f)-[r:IMPORTS]->(m)
|
|
528
575
|
SET r += $rel_props
|
|
529
|
-
""", **
|
|
576
|
+
""", **sanitized)
|
|
530
577
|
|
|
531
578
|
|
|
532
579
|
# Handle CONTAINS relationship between class to their children like variables
|
|
533
580
|
for func in file_data.get('functions', []):
|
|
534
581
|
if func.get('class_context'):
|
|
535
|
-
|
|
582
|
+
# Try same-file match first (Python, JS, etc.)
|
|
583
|
+
if not self._safe_run_create(session, """
|
|
536
584
|
MATCH (c:Class {name: $class_name, path: $path})
|
|
537
585
|
MATCH (fn:Function {name: $func_name, path: $path, line_number: $func_line})
|
|
538
586
|
MERGE (c)-[:CONTAINS]->(fn)
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
587
|
+
RETURN count(*) as created
|
|
588
|
+
""", {
|
|
589
|
+
'class_name': func['class_context'],
|
|
590
|
+
'path': file_path_str,
|
|
591
|
+
'func_name': func['name'],
|
|
592
|
+
'func_line': func['line_number']
|
|
593
|
+
}):
|
|
594
|
+
# Cross-file match for C/C++ where class is in .h and method in .cpp.
|
|
595
|
+
# Note: matches by class name only (no path constraint), so classes
|
|
596
|
+
# with identical names in different files could get false links.
|
|
597
|
+
self._safe_run_create(session, """
|
|
598
|
+
MATCH (c:Class {name: $class_name})
|
|
599
|
+
MATCH (fn:Function {name: $func_name, path: $path, line_number: $func_line})
|
|
600
|
+
MERGE (c)-[:CONTAINS]->(fn)
|
|
601
|
+
RETURN count(*) as created
|
|
602
|
+
""", {
|
|
603
|
+
'class_name': func['class_context'],
|
|
604
|
+
'path': file_path_str,
|
|
605
|
+
'func_name': func['name'],
|
|
606
|
+
'func_line': func['line_number']
|
|
607
|
+
})
|
|
544
608
|
|
|
545
609
|
# --- NEW: Class INCLUDES Module (Ruby mixins) ---
|
|
546
610
|
for inc in file_data.get('module_inclusions', []):
|
|
@@ -693,7 +757,7 @@ class GraphBuilder:
|
|
|
693
757
|
|
|
694
758
|
# KùzuDB workaround: Try Function->Function first, then other combinations
|
|
695
759
|
# This avoids polymorphic MERGE which KùzuDB doesn't support
|
|
696
|
-
call_params = {
|
|
760
|
+
call_params = self._sanitize_props({
|
|
697
761
|
'caller_name': caller_name,
|
|
698
762
|
'caller_file_path': caller_file_path,
|
|
699
763
|
'caller_line_number': caller_line_number,
|
|
@@ -702,8 +766,9 @@ class GraphBuilder:
|
|
|
702
766
|
'line_number': call['line_number'],
|
|
703
767
|
'args': call.get('args', []),
|
|
704
768
|
'full_call_name': call.get('full_name', called_name)
|
|
705
|
-
}
|
|
706
|
-
|
|
769
|
+
})
|
|
770
|
+
|
|
771
|
+
# Try Function caller -> Function callee
|
|
707
772
|
if not self._safe_run_create(session, """
|
|
708
773
|
OPTIONAL MATCH (caller:Function {name: $caller_name, path: $caller_file_path})
|
|
709
774
|
OPTIONAL MATCH (called:Function {name: $called_name, path: $called_file_path})
|
|
@@ -782,14 +847,15 @@ class GraphBuilder:
|
|
|
782
847
|
""", call_params)
|
|
783
848
|
else:
|
|
784
849
|
# File-level calls: Try Function first, then Class
|
|
785
|
-
call_params = {
|
|
850
|
+
call_params = self._sanitize_props({
|
|
786
851
|
'caller_file_path': caller_file_path,
|
|
787
852
|
'called_name': called_name,
|
|
788
853
|
'called_file_path': resolved_path,
|
|
789
854
|
'line_number': call['line_number'],
|
|
790
855
|
'args': call.get('args', []),
|
|
791
856
|
'full_call_name': call.get('full_name', called_name)
|
|
792
|
-
}
|
|
857
|
+
})
|
|
858
|
+
|
|
793
859
|
|
|
794
860
|
if not self._safe_run_create(session, """
|
|
795
861
|
OPTIONAL MATCH (caller:File {path: $caller_file_path})
|
|
@@ -1162,13 +1228,16 @@ class GraphBuilder:
|
|
|
1162
1228
|
|
|
1163
1229
|
# Step 4: Write nodes to graph using existing add_file_to_graph()
|
|
1164
1230
|
processed = 0
|
|
1231
|
+
index_root = path.resolve()
|
|
1165
1232
|
for abs_path_str, file_data in files_data.items():
|
|
1166
|
-
|
|
1233
|
+
file_path = Path(abs_path_str)
|
|
1234
|
+
if file_path.is_file() and file_path_has_ignore_dir_segment(file_path, index_root):
|
|
1235
|
+
continue
|
|
1236
|
+
file_data["repo_path"] = str(index_root)
|
|
1167
1237
|
if job_id:
|
|
1168
1238
|
self.job_manager.update_job(job_id, current_file=abs_path_str)
|
|
1169
1239
|
|
|
1170
1240
|
# Step 5: Tree-sitter supplement — add source text, complexity, imports and bases
|
|
1171
|
-
file_path = Path(abs_path_str)
|
|
1172
1241
|
ts_parser = self.get_parser(file_path.suffix)
|
|
1173
1242
|
if file_path.exists() and ts_parser:
|
|
1174
1243
|
try:
|