codegraphcontext 0.3.7__tar.gz → 0.3.9__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.9}/PKG-INFO +5 -3
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/README.md +3 -2
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/pyproject.toml +2 -1
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/cli/cli_helpers.py +121 -96
- codegraphcontext-0.3.9/src/codegraphcontext/cli/config_manager.py +878 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/cli/main.py +252 -122
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/core/__init__.py +11 -12
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/core/cgc_bundle.py +95 -21
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/core/database_falkordb.py +24 -11
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/core/database_kuzu.py +214 -44
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/core/watcher.py +85 -28
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/server.py +46 -5
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/code_finder.py +117 -64
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/graph_builder.py +756 -546
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/cpp.py +137 -72
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/go.py +42 -5
- codegraphcontext-0.3.9/src/codegraphcontext/utils/path_ignore.py +55 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/utils/tree_sitter_manager.py +8 -9
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9/src/codegraphcontext.egg-info}/PKG-INFO +5 -3
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext.egg-info/SOURCES.txt +1 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext.egg-info/requires.txt +1 -0
- codegraphcontext-0.3.7/src/codegraphcontext/cli/config_manager.py +0 -412
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/LICENSE +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/MANIFEST.in +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/setup.cfg +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/__init__.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/__main__.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/cli/__init__.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/cli/registry_commands.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/cli/setup_macos.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/cli/setup_wizard.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/cli/visualizer.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/core/bundle_registry.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/core/database.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/core/database_falkordb_remote.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/core/falkor_worker.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/core/jobs.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/prompts.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tool_definitions.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/__init__.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/advanced_language_query_tool.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/handlers/analysis_handlers.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/handlers/indexing_handlers.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/handlers/management_handlers.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/handlers/query_handlers.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/handlers/watcher_handlers.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/c.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/csharp.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/dart.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/elixir.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/haskell.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/java.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/javascript.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/kotlin.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/perl.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/php.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/python.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/ruby.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/rust.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/scala.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/swift.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/typescript.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/languages/typescriptjsx.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/package_resolver.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/c_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/dart_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/go_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/haskell_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/java_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/perl_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/python_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/rust_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/scala_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/swift_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/scip_indexer.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/scip_pb2.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/tools/system.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/utils/debug_log.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/utils/visualize_graph.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext/viz/server.py +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext.egg-info/dependency_links.txt +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/src/codegraphcontext.egg-info/entry_points.txt +0 -0
- {codegraphcontext-0.3.7 → codegraphcontext-0.3.9}/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.9
|
|
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
|
|
@@ -72,6 +73,7 @@ Dynamic: license-file
|
|
|
72
73
|
- 🇬🇧 [English](README.md)
|
|
73
74
|
- 🇨🇳 [中文](README.zh-CN.md)
|
|
74
75
|
- 🇰🇷 [한국어](README.kor.md)
|
|
76
|
+
- 🇺🇦 [Українська](README.uk.md)
|
|
75
77
|
- 🇯🇵 日本語 (Soon)
|
|
76
78
|
- 🇷🇺 Русский (Soon)
|
|
77
79
|
- 🇪🇸 Español (Soon)
|
|
@@ -162,7 +164,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
|
|
|
162
164
|
---
|
|
163
165
|
|
|
164
166
|
## Project Details
|
|
165
|
-
- **Version:** 0.3.
|
|
167
|
+
- **Version:** 0.3.9
|
|
166
168
|
- **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
|
|
167
169
|
- **License:** MIT License (See [LICENSE](LICENSE) for details)
|
|
168
170
|
- **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
|
|
@@ -271,7 +273,7 @@ pip install codegraphcontext
|
|
|
271
273
|
|
|
272
274
|
### If 'cgc' command isn't found, run our one-line fix:
|
|
273
275
|
```
|
|
274
|
-
curl -sSL
|
|
276
|
+
curl -sSL https://raw.githubusercontent.com/CodeGraphContext/CodeGraphContext/main/scripts/post_install_fix.sh | bash
|
|
275
277
|
```
|
|
276
278
|
|
|
277
279
|
---
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
- 🇬🇧 [English](README.md)
|
|
7
7
|
- 🇨🇳 [中文](README.zh-CN.md)
|
|
8
8
|
- 🇰🇷 [한국어](README.kor.md)
|
|
9
|
+
- 🇺🇦 [Українська](README.uk.md)
|
|
9
10
|
- 🇯🇵 日本語 (Soon)
|
|
10
11
|
- 🇷🇺 Русский (Soon)
|
|
11
12
|
- 🇪🇸 Español (Soon)
|
|
@@ -96,7 +97,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
|
|
|
96
97
|
---
|
|
97
98
|
|
|
98
99
|
## Project Details
|
|
99
|
-
- **Version:** 0.3.
|
|
100
|
+
- **Version:** 0.3.9
|
|
100
101
|
- **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
|
|
101
102
|
- **License:** MIT License (See [LICENSE](LICENSE) for details)
|
|
102
103
|
- **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
|
|
@@ -205,7 +206,7 @@ pip install codegraphcontext
|
|
|
205
206
|
|
|
206
207
|
### If 'cgc' command isn't found, run our one-line fix:
|
|
207
208
|
```
|
|
208
|
-
curl -sSL
|
|
209
|
+
curl -sSL https://raw.githubusercontent.com/CodeGraphContext/CodeGraphContext/main/scripts/post_install_fix.sh | bash
|
|
209
210
|
```
|
|
210
211
|
|
|
211
212
|
---
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "codegraphcontext"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.9"
|
|
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"
|
|
@@ -4,7 +4,8 @@ import uuid
|
|
|
4
4
|
import urllib.parse
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
import time
|
|
7
|
-
|
|
7
|
+
import os
|
|
8
|
+
from typing import Optional, List, Dict, Any
|
|
8
9
|
from rich.console import Console
|
|
9
10
|
from rich.table import Table
|
|
10
11
|
from rich.progress import (
|
|
@@ -22,18 +23,41 @@ from ..core.jobs import JobManager
|
|
|
22
23
|
from ..tools.code_finder import CodeFinder
|
|
23
24
|
from ..tools.graph_builder import GraphBuilder
|
|
24
25
|
from ..tools.package_resolver import get_local_package_path
|
|
26
|
+
from ..utils.debug_log import info_logger, warning_logger
|
|
27
|
+
from .config_manager import resolve_context, ResolvedContext, register_repo_in_context, ensure_first_run_bootstrap
|
|
25
28
|
|
|
26
29
|
console = Console()
|
|
27
30
|
|
|
28
31
|
|
|
29
|
-
def _initialize_services():
|
|
30
|
-
"""
|
|
32
|
+
def _initialize_services(cli_context_flag: Optional[str] = None) -> tuple[Any, Any, Any, ResolvedContext]:
|
|
33
|
+
"""
|
|
34
|
+
Initializes and returns core service managers based on the resolved context.
|
|
35
|
+
Returns (db_manager, graph_builder, code_finder, resolved_context).
|
|
36
|
+
"""
|
|
37
|
+
ensure_first_run_bootstrap()
|
|
38
|
+
console.print("[dim]Resolving context...[/dim]")
|
|
39
|
+
ctx = resolve_context(cli_context_flag)
|
|
40
|
+
|
|
41
|
+
# Let the user know what context we're operating in
|
|
42
|
+
if ctx.mode == "named":
|
|
43
|
+
console.print(f"[cyan]Context:[/cyan] {ctx.context_name} (Database: {ctx.database})")
|
|
44
|
+
elif ctx.mode == "per-repo":
|
|
45
|
+
console.print(f"[cyan]Context:[/cyan] Per-repo local mode (Database: {ctx.database})")
|
|
46
|
+
else:
|
|
47
|
+
# Default global mode — silent to keep CLI clean for existing users
|
|
48
|
+
pass
|
|
49
|
+
|
|
31
50
|
console.print("[dim]Initializing services and database connection...[/dim]")
|
|
32
51
|
try:
|
|
33
|
-
|
|
52
|
+
# Override the database backend with the context's specific choice
|
|
53
|
+
if ctx.database:
|
|
54
|
+
os.environ['CGC_RUNTIME_DB_TYPE'] = ctx.database
|
|
55
|
+
|
|
56
|
+
# Pass the exact DB path resolved from the context
|
|
57
|
+
db_manager = get_database_manager(db_path=ctx.db_path)
|
|
34
58
|
except ValueError as e:
|
|
35
59
|
console.print(f"[bold red]Database Configuration Error:[/bold red] {e}")
|
|
36
|
-
return None, None, None
|
|
60
|
+
return None, None, None, ctx
|
|
37
61
|
|
|
38
62
|
try:
|
|
39
63
|
db_manager.get_driver()
|
|
@@ -58,11 +82,11 @@ def _initialize_services():
|
|
|
58
82
|
console.print("[green]✓[/green] Successfully switched to KùzuDB fallback")
|
|
59
83
|
except Exception as kuzu_e:
|
|
60
84
|
console.print(f"[bold red]Critical Error:[/bold red] Both FalkorDB and KùzuDB failed: {kuzu_e}")
|
|
61
|
-
return None, None, None
|
|
85
|
+
return None, None, None, ctx
|
|
62
86
|
else:
|
|
63
87
|
console.print(f"[bold red]Database Connection Error:[/bold red] {e}")
|
|
64
88
|
console.print("Please ensure your database is configured correctly or run 'cgc doctor'.")
|
|
65
|
-
return None, None, None
|
|
89
|
+
return None, None, None, ctx
|
|
66
90
|
|
|
67
91
|
# The GraphBuilder requires an event loop, even for synchronous-style execution
|
|
68
92
|
try:
|
|
@@ -74,10 +98,10 @@ def _initialize_services():
|
|
|
74
98
|
graph_builder = GraphBuilder(db_manager, JobManager(), loop)
|
|
75
99
|
code_finder = CodeFinder(db_manager)
|
|
76
100
|
console.print("[dim]Services initialized.[/dim]")
|
|
77
|
-
return db_manager, graph_builder, code_finder
|
|
101
|
+
return db_manager, graph_builder, code_finder, ctx
|
|
78
102
|
|
|
79
103
|
|
|
80
|
-
async def _run_index_with_progress(graph_builder: GraphBuilder, path_obj: Path, is_dependency: bool = False):
|
|
104
|
+
async def _run_index_with_progress(graph_builder: GraphBuilder, path_obj: Path, is_dependency: bool = False, cgcignore_path: str = None):
|
|
81
105
|
"""Internal helper to run indexing with a Live progress bar."""
|
|
82
106
|
job_id = graph_builder.job_manager.create_job(str(path_obj), is_dependency=is_dependency)
|
|
83
107
|
|
|
@@ -101,7 +125,7 @@ async def _run_index_with_progress(graph_builder: GraphBuilder, path_obj: Path,
|
|
|
101
125
|
)
|
|
102
126
|
|
|
103
127
|
indexing_task = asyncio.create_task(
|
|
104
|
-
graph_builder.build_graph_from_path_async(path_obj, is_dependency=is_dependency, job_id=job_id)
|
|
128
|
+
graph_builder.build_graph_from_path_async(path_obj, is_dependency=is_dependency, job_id=job_id, cgcignore_path=cgcignore_path)
|
|
105
129
|
)
|
|
106
130
|
|
|
107
131
|
from ..core.jobs import JobStatus
|
|
@@ -135,14 +159,14 @@ async def _run_index_with_progress(graph_builder: GraphBuilder, path_obj: Path,
|
|
|
135
159
|
raise e
|
|
136
160
|
|
|
137
161
|
|
|
138
|
-
def index_helper(path: str):
|
|
139
|
-
"""Synchronously indexes a repository."""
|
|
162
|
+
def index_helper(path: str, context: Optional[str] = None):
|
|
163
|
+
"""Synchronously indexes a repository in a given context."""
|
|
140
164
|
time_start = time.time()
|
|
141
|
-
services = _initialize_services()
|
|
142
|
-
if not all(services):
|
|
165
|
+
services = _initialize_services(context)
|
|
166
|
+
if not all(services[:3]):
|
|
143
167
|
return
|
|
144
168
|
|
|
145
|
-
db_manager, graph_builder, code_finder = services
|
|
169
|
+
db_manager, graph_builder, code_finder, ctx = services
|
|
146
170
|
path_obj = Path(path).resolve()
|
|
147
171
|
|
|
148
172
|
if not path_obj.exists():
|
|
@@ -155,10 +179,12 @@ def index_helper(path: str):
|
|
|
155
179
|
|
|
156
180
|
if repo_exists:
|
|
157
181
|
# Check if the repository actually has files (not just an empty node from interrupted indexing)
|
|
182
|
+
# Use variable-length path to handle both flat (Repository->File) and
|
|
183
|
+
# hierarchical (Repository->Directory->...->File) graph structures
|
|
158
184
|
try:
|
|
159
185
|
with db_manager.get_driver().session() as session:
|
|
160
186
|
result = session.run(
|
|
161
|
-
"MATCH (r:Repository {path: $path})-[:CONTAINS]->(f:File) RETURN count(f) as file_count",
|
|
187
|
+
"MATCH (r:Repository {path: $path})-[:CONTAINS*]->(f:File) RETURN count(f) as file_count",
|
|
162
188
|
path=str(path_obj)
|
|
163
189
|
)
|
|
164
190
|
record = result.single()
|
|
@@ -174,10 +200,14 @@ def index_helper(path: str):
|
|
|
174
200
|
except Exception as e:
|
|
175
201
|
console.print(f"[yellow]Warning: Could not check file count: {e}. Proceeding with indexing...[/yellow]")
|
|
176
202
|
|
|
203
|
+
# Auto-register the repo into the named context (auto-creates if needed)
|
|
204
|
+
if context and ctx.mode == "named":
|
|
205
|
+
register_repo_in_context(context, str(path_obj), auto_create=True)
|
|
206
|
+
|
|
177
207
|
console.print(f"Starting indexing for: {path_obj}")
|
|
178
208
|
|
|
179
209
|
try:
|
|
180
|
-
asyncio.run(_run_index_with_progress(graph_builder, path_obj, is_dependency=False))
|
|
210
|
+
asyncio.run(_run_index_with_progress(graph_builder, path_obj, is_dependency=False, cgcignore_path=ctx.cgcignore_path))
|
|
181
211
|
time_end = time.time()
|
|
182
212
|
elapsed = time_end - time_start
|
|
183
213
|
console.print(f"[green]Successfully finished indexing: {path} in {elapsed:.2f} seconds[/green]")
|
|
@@ -200,13 +230,13 @@ def index_helper(path: str):
|
|
|
200
230
|
db_manager.close_driver()
|
|
201
231
|
|
|
202
232
|
|
|
203
|
-
def add_package_helper(package_name: str, language: str):
|
|
233
|
+
def add_package_helper(package_name: str, language: str, context: Optional[str] = None):
|
|
204
234
|
"""Synchronously indexes a package."""
|
|
205
|
-
services = _initialize_services()
|
|
206
|
-
if not all(services):
|
|
235
|
+
services = _initialize_services(context)
|
|
236
|
+
if not all(services[:3]):
|
|
207
237
|
return
|
|
208
238
|
|
|
209
|
-
db_manager, graph_builder, code_finder = services
|
|
239
|
+
db_manager, graph_builder, code_finder, ctx = services
|
|
210
240
|
|
|
211
241
|
package_path_str = get_local_package_path(package_name, language)
|
|
212
242
|
if not package_path_str:
|
|
@@ -225,7 +255,7 @@ def add_package_helper(package_name: str, language: str):
|
|
|
225
255
|
console.print(f"Starting indexing for package '{package_name}' at: {package_path}")
|
|
226
256
|
|
|
227
257
|
try:
|
|
228
|
-
asyncio.run(_run_index_with_progress(graph_builder, package_path, is_dependency=True))
|
|
258
|
+
asyncio.run(_run_index_with_progress(graph_builder, package_path, is_dependency=True, cgcignore_path=ctx.cgcignore_path))
|
|
229
259
|
console.print(f"[green]Successfully finished indexing package: {package_name}[/green]")
|
|
230
260
|
except Exception as e:
|
|
231
261
|
console.print(f"[bold red]An error occurred during package indexing:[/bold red] {e}")
|
|
@@ -233,13 +263,13 @@ def add_package_helper(package_name: str, language: str):
|
|
|
233
263
|
db_manager.close_driver()
|
|
234
264
|
|
|
235
265
|
|
|
236
|
-
def list_repos_helper():
|
|
266
|
+
def list_repos_helper(context: Optional[str] = None):
|
|
237
267
|
"""Lists all indexed repositories."""
|
|
238
|
-
services = _initialize_services()
|
|
239
|
-
if not all(services):
|
|
268
|
+
services = _initialize_services(context)
|
|
269
|
+
if not all(services[:3]):
|
|
240
270
|
return
|
|
241
271
|
|
|
242
|
-
db_manager, _, code_finder = services
|
|
272
|
+
db_manager, _, code_finder, ctx = services
|
|
243
273
|
|
|
244
274
|
try:
|
|
245
275
|
repos = code_finder.list_indexed_repositories()
|
|
@@ -263,13 +293,13 @@ def list_repos_helper():
|
|
|
263
293
|
db_manager.close_driver()
|
|
264
294
|
|
|
265
295
|
|
|
266
|
-
def delete_helper(repo_path: str):
|
|
296
|
+
def delete_helper(repo_path: str, context: Optional[str] = None):
|
|
267
297
|
"""Deletes a repository from the graph."""
|
|
268
|
-
services = _initialize_services()
|
|
269
|
-
if not all(services):
|
|
298
|
+
services = _initialize_services(context)
|
|
299
|
+
if not all(services[:3]):
|
|
270
300
|
return
|
|
271
301
|
|
|
272
|
-
db_manager, graph_builder, _ = services
|
|
302
|
+
db_manager, graph_builder, _, ctx = services
|
|
273
303
|
|
|
274
304
|
try:
|
|
275
305
|
if graph_builder.delete_repository_from_graph(repo_path):
|
|
@@ -283,13 +313,13 @@ def delete_helper(repo_path: str):
|
|
|
283
313
|
db_manager.close_driver()
|
|
284
314
|
|
|
285
315
|
|
|
286
|
-
def cypher_helper(query: str):
|
|
316
|
+
def cypher_helper(query: str, context: Optional[str] = None):
|
|
287
317
|
"""Executes a read-only Cypher query."""
|
|
288
|
-
services = _initialize_services()
|
|
289
|
-
if not all(services):
|
|
318
|
+
services = _initialize_services(context)
|
|
319
|
+
if not all(services[:3]):
|
|
290
320
|
return
|
|
291
321
|
|
|
292
|
-
db_manager, _, _ = services
|
|
322
|
+
db_manager, _, _, ctx = services
|
|
293
323
|
|
|
294
324
|
# Replicating safety checks from MCPServer
|
|
295
325
|
forbidden_keywords = ['CREATE', 'MERGE', 'DELETE', 'SET', 'REMOVE', 'DROP', 'CALL apoc']
|
|
@@ -309,15 +339,15 @@ def cypher_helper(query: str):
|
|
|
309
339
|
db_manager.close_driver()
|
|
310
340
|
|
|
311
341
|
|
|
312
|
-
def cypher_helper_visual(query: str):
|
|
342
|
+
def cypher_helper_visual(query: str, context: Optional[str] = None):
|
|
313
343
|
"""Executes a read-only Cypher query and visualizes the results."""
|
|
314
344
|
from .visualizer import visualize_cypher_results
|
|
315
345
|
|
|
316
|
-
services = _initialize_services()
|
|
317
|
-
if not all(services):
|
|
346
|
+
services = _initialize_services(context)
|
|
347
|
+
if not all(services[:3]):
|
|
318
348
|
return
|
|
319
349
|
|
|
320
|
-
db_manager, _, _ = services
|
|
350
|
+
db_manager, _, _, ctx = services
|
|
321
351
|
|
|
322
352
|
# Replicating safety checks from MCPServer
|
|
323
353
|
forbidden_keywords = ['CREATE', 'MERGE', 'DELETE', 'SET', 'REMOVE', 'DROP', 'CALL apoc']
|
|
@@ -346,13 +376,13 @@ import uvicorn
|
|
|
346
376
|
import urllib.parse
|
|
347
377
|
from ..viz.server import run_server, set_db_manager
|
|
348
378
|
|
|
349
|
-
def visualize_helper(repo_path: Optional[str] = None, port: int = 8000):
|
|
379
|
+
def visualize_helper(repo_path: Optional[str] = None, port: int = 8000, context: Optional[str] = None):
|
|
350
380
|
""""Generates an interactive visualization using the Playground UI."""
|
|
351
|
-
services = _initialize_services()
|
|
352
|
-
if not all(services):
|
|
381
|
+
services = _initialize_services(context)
|
|
382
|
+
if not all(services[:3]):
|
|
353
383
|
return
|
|
354
384
|
|
|
355
|
-
db_manager, _, _ = services
|
|
385
|
+
db_manager, _, _, ctx = services
|
|
356
386
|
|
|
357
387
|
# Set the DB manager for the server
|
|
358
388
|
set_db_manager(db_manager)
|
|
@@ -424,14 +454,14 @@ def visualize_helper(repo_path: Optional[str] = None, port: int = 8000):
|
|
|
424
454
|
db_manager.close_driver()
|
|
425
455
|
|
|
426
456
|
|
|
427
|
-
def reindex_helper(path: str):
|
|
457
|
+
def reindex_helper(path: str, context: Optional[str] = None):
|
|
428
458
|
"""Force re-index by deleting and rebuilding the repository."""
|
|
429
459
|
time_start = time.time()
|
|
430
|
-
services = _initialize_services()
|
|
431
|
-
if not all(services):
|
|
460
|
+
services = _initialize_services(context)
|
|
461
|
+
if not all(services[:3]):
|
|
432
462
|
return
|
|
433
463
|
|
|
434
|
-
db_manager, graph_builder, code_finder = services
|
|
464
|
+
db_manager, graph_builder, code_finder, ctx = services
|
|
435
465
|
path_obj = Path(path).resolve()
|
|
436
466
|
|
|
437
467
|
if not path_obj.exists():
|
|
@@ -456,7 +486,7 @@ def reindex_helper(path: str):
|
|
|
456
486
|
console.print(f"[cyan]Re-indexing: {path_obj}[/cyan]")
|
|
457
487
|
|
|
458
488
|
try:
|
|
459
|
-
asyncio.run(_run_index_with_progress(graph_builder, path_obj, is_dependency=False))
|
|
489
|
+
asyncio.run(_run_index_with_progress(graph_builder, path_obj, is_dependency=False, cgcignore_path=ctx.cgcignore_path))
|
|
460
490
|
time_end = time.time()
|
|
461
491
|
elapsed = time_end - time_start
|
|
462
492
|
console.print(f"[green]Successfully re-indexed: {path} in {elapsed:.2f} seconds[/green]")
|
|
@@ -466,60 +496,39 @@ def reindex_helper(path: str):
|
|
|
466
496
|
db_manager.close_driver()
|
|
467
497
|
|
|
468
498
|
|
|
469
|
-
def update_helper(path: str):
|
|
499
|
+
def update_helper(path: str, context: Optional[str] = None):
|
|
470
500
|
"""Update/refresh index for a path (alias for reindex)."""
|
|
471
501
|
console.print("[cyan]Updating repository index...[/cyan]")
|
|
472
|
-
reindex_helper(path)
|
|
502
|
+
reindex_helper(path, context)
|
|
473
503
|
|
|
474
504
|
|
|
475
|
-
def clean_helper():
|
|
505
|
+
def clean_helper(context: Optional[str] = None):
|
|
476
506
|
"""Remove orphaned nodes and relationships from the database."""
|
|
477
|
-
services = _initialize_services()
|
|
478
|
-
if not all(services):
|
|
507
|
+
services = _initialize_services(context)
|
|
508
|
+
if not all(services[:3]):
|
|
479
509
|
return
|
|
480
510
|
|
|
481
|
-
db_manager, _, _ = services
|
|
511
|
+
db_manager, _, _, ctx = services
|
|
482
512
|
|
|
483
513
|
console.print("[cyan]🧹 Cleaning database (removing orphaned nodes)...[/cyan]")
|
|
484
514
|
|
|
485
515
|
try:
|
|
486
|
-
# Determine if we're using FalkorDB or Neo4j for query optimization
|
|
487
|
-
db_type = db_manager.__class__.__name__
|
|
488
|
-
is_falkordb = "Falkor" in db_type
|
|
489
|
-
|
|
490
516
|
total_deleted = 0
|
|
491
|
-
batch_size =
|
|
517
|
+
batch_size = 500
|
|
492
518
|
|
|
493
519
|
with db_manager.get_driver().session() as session:
|
|
494
|
-
#
|
|
520
|
+
# Layer-by-layer deletion: iteratively delete nodes that lost
|
|
521
|
+
# their CONTAINS parent. Each pass peels one layer of the
|
|
522
|
+
# Repository → File → Class/Function → Variable hierarchy.
|
|
495
523
|
while True:
|
|
496
|
-
|
|
497
|
-
# FalkorDB-compatible query using OPTIONAL MATCH
|
|
498
|
-
query = """
|
|
499
|
-
MATCH (n)
|
|
500
|
-
WHERE NOT (n:Repository)
|
|
501
|
-
OPTIONAL MATCH path = (n)-[*..10]-(r:Repository)
|
|
502
|
-
WITH n, path
|
|
503
|
-
WHERE path IS NULL
|
|
504
|
-
WITH n LIMIT $batch_size
|
|
505
|
-
DETACH DELETE n
|
|
506
|
-
RETURN count(n) as deleted
|
|
507
|
-
"""
|
|
508
|
-
else:
|
|
509
|
-
# Neo4j optimized query using NOT EXISTS with bounded path
|
|
510
|
-
# This is much faster than OPTIONAL MATCH with variable-length paths
|
|
511
|
-
query = """
|
|
524
|
+
result = session.run("""
|
|
512
525
|
MATCH (n)
|
|
513
|
-
WHERE NOT
|
|
514
|
-
AND NOT
|
|
515
|
-
MATCH (n)-[*..10]-(r:Repository)
|
|
516
|
-
}
|
|
526
|
+
WHERE NOT n:Repository
|
|
527
|
+
AND NOT ()-[:CONTAINS]->(n)
|
|
517
528
|
WITH n LIMIT $batch_size
|
|
518
529
|
DETACH DELETE n
|
|
519
530
|
RETURN count(n) as deleted
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
result = session.run(query, batch_size=batch_size)
|
|
531
|
+
""", batch_size=batch_size)
|
|
523
532
|
record = result.single()
|
|
524
533
|
deleted_count = record["deleted"] if record else 0
|
|
525
534
|
total_deleted += deleted_count
|
|
@@ -527,17 +536,13 @@ def clean_helper():
|
|
|
527
536
|
if deleted_count == 0:
|
|
528
537
|
break
|
|
529
538
|
|
|
530
|
-
console.print(f"[dim]Deleted {deleted_count} orphaned nodes (batch)...[/dim]")
|
|
539
|
+
console.print(f"[dim] Deleted {deleted_count} orphaned nodes (batch)...[/dim]")
|
|
531
540
|
|
|
532
541
|
if total_deleted > 0:
|
|
533
542
|
console.print(f"[green]✓[/green] Deleted {total_deleted} orphaned nodes total")
|
|
534
543
|
else:
|
|
535
544
|
console.print("[green]✓[/green] No orphaned nodes found")
|
|
536
545
|
|
|
537
|
-
# Clean up any duplicate relationships (if any)
|
|
538
|
-
console.print("[dim]Checking for duplicate relationships...[/dim]")
|
|
539
|
-
# Note: This is database-specific and might not work for all backends
|
|
540
|
-
|
|
541
546
|
console.print("[green]✅ Database cleanup complete![/green]")
|
|
542
547
|
except Exception as e:
|
|
543
548
|
console.print(f"[bold red]An error occurred during cleanup:[/bold red] {e}")
|
|
@@ -545,13 +550,13 @@ def clean_helper():
|
|
|
545
550
|
db_manager.close_driver()
|
|
546
551
|
|
|
547
552
|
|
|
548
|
-
def stats_helper(path: str = None):
|
|
553
|
+
def stats_helper(path: str = None, context: Optional[str] = None):
|
|
549
554
|
"""Show indexing statistics for a repository or overall."""
|
|
550
|
-
services = _initialize_services()
|
|
551
|
-
if not all(services):
|
|
555
|
+
services = _initialize_services(context)
|
|
556
|
+
if not all(services[:3]):
|
|
552
557
|
return
|
|
553
558
|
|
|
554
|
-
db_manager, _, code_finder = services
|
|
559
|
+
db_manager, _, code_finder, ctx = services
|
|
555
560
|
|
|
556
561
|
try:
|
|
557
562
|
if path:
|
|
@@ -633,7 +638,7 @@ def stats_helper(path: str = None):
|
|
|
633
638
|
db_manager.close_driver()
|
|
634
639
|
|
|
635
640
|
|
|
636
|
-
def watch_helper(path: str):
|
|
641
|
+
def watch_helper(path: str, context: Optional[str] = None):
|
|
637
642
|
"""Watch a directory for changes and auto-update the graph (blocking mode)."""
|
|
638
643
|
import logging
|
|
639
644
|
from ..core.watcher import CodeWatcher
|
|
@@ -643,11 +648,11 @@ def watch_helper(path: str):
|
|
|
643
648
|
logging.getLogger('watchdog.observers').setLevel(logging.WARNING)
|
|
644
649
|
logging.getLogger('watchdog.observers.inotify_buffer').setLevel(logging.WARNING)
|
|
645
650
|
|
|
646
|
-
services = _initialize_services()
|
|
647
|
-
if not all(services):
|
|
651
|
+
services = _initialize_services(context)
|
|
652
|
+
if not all(services[:3]):
|
|
648
653
|
return
|
|
649
654
|
|
|
650
|
-
db_manager, graph_builder, code_finder = services
|
|
655
|
+
db_manager, graph_builder, code_finder, ctx = services
|
|
651
656
|
path_obj = Path(path).resolve()
|
|
652
657
|
|
|
653
658
|
if not path_obj.exists():
|
|
@@ -662,9 +667,29 @@ def watch_helper(path: str):
|
|
|
662
667
|
|
|
663
668
|
console.print(f"[bold cyan]🔍 Watching {path_obj} for changes...[/bold cyan]")
|
|
664
669
|
|
|
665
|
-
# Check if already indexed
|
|
670
|
+
# Check if already indexed — use File node count as a robust fallback so a
|
|
671
|
+
# transient empty result from list_indexed_repositories never triggers a
|
|
672
|
+
# destructive full rescan of an already-populated graph.
|
|
666
673
|
indexed_repos = code_finder.list_indexed_repositories()
|
|
667
674
|
is_indexed = any(Path(repo["path"]).resolve() == path_obj for repo in indexed_repos)
|
|
675
|
+
if not is_indexed:
|
|
676
|
+
# Fallback: count File nodes whose path starts with this repo's path.
|
|
677
|
+
# If > 100 exist, the repo is clearly already indexed — skip the scan.
|
|
678
|
+
try:
|
|
679
|
+
with code_finder.driver.session() as _s:
|
|
680
|
+
_r = _s.run(
|
|
681
|
+
"MATCH (n:File) WHERE n.path STARTS WITH $p RETURN count(n) AS c",
|
|
682
|
+
p=str(path_obj) + "/"
|
|
683
|
+
)
|
|
684
|
+
_count = _r.single()["c"]
|
|
685
|
+
if _count > 100:
|
|
686
|
+
info_logger(
|
|
687
|
+
f"[watch] list_indexed_repositories returned no match for {path_obj} "
|
|
688
|
+
f"but {_count} File nodes exist — treating as already indexed."
|
|
689
|
+
)
|
|
690
|
+
is_indexed = True
|
|
691
|
+
except Exception as _e:
|
|
692
|
+
warning_logger(f"[watch] Fallback indexed check failed: {_e}")
|
|
668
693
|
|
|
669
694
|
# Create watcher instance
|
|
670
695
|
job_manager = JobManager()
|