codegraphcontext 0.4.12__py3-none-any.whl → 0.4.14__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- codegraphcontext/api/router.py +1 -1
- codegraphcontext/cli/config_manager.py +15 -13
- codegraphcontext/cli/main.py +39 -42
- codegraphcontext/cli/registry_commands.py +30 -19
- codegraphcontext/cli/setup_wizard.py +21 -9
- codegraphcontext/core/__init__.py +35 -1
- codegraphcontext/core/bundle_registry.py +2 -42
- codegraphcontext/core/cgc_bundle.py +101 -42
- codegraphcontext/core/database_falkordb.py +88 -14
- codegraphcontext/core/database_kuzu.py +5 -2
- codegraphcontext/core/database_nornic.py +11 -3
- codegraphcontext/server.py +11 -1
- codegraphcontext/tools/advanced_language_query_tool.py +13 -12
- codegraphcontext/tools/code_finder.py +4 -2
- codegraphcontext/tools/graph_builder.py +10 -2
- codegraphcontext/tools/indexing/persistence/writer.py +36 -10
- codegraphcontext/tools/indexing/pre_scan.py +4 -0
- codegraphcontext/tools/indexing/resolution/calls.py +2 -1
- codegraphcontext/tools/indexing/scip_pipeline.py +1 -1
- codegraphcontext/tools/languages/elisp.py +682 -0
- codegraphcontext/tools/query_tool_languages/elisp_toolkit.py +73 -0
- codegraphcontext/tools/scip_indexer.py +4 -13
- codegraphcontext/tools/system.py +8 -3
- codegraphcontext/tools/tree_sitter_parser.py +4 -0
- codegraphcontext/utils/tree_sitter_manager.py +5 -0
- codegraphcontext/viz/server.py +4 -2
- {codegraphcontext-0.4.12.dist-info → codegraphcontext-0.4.14.dist-info}/METADATA +40 -17
- {codegraphcontext-0.4.12.dist-info → codegraphcontext-0.4.14.dist-info}/RECORD +32 -30
- {codegraphcontext-0.4.12.dist-info → codegraphcontext-0.4.14.dist-info}/WHEEL +0 -0
- {codegraphcontext-0.4.12.dist-info → codegraphcontext-0.4.14.dist-info}/entry_points.txt +0 -0
- {codegraphcontext-0.4.12.dist-info → codegraphcontext-0.4.14.dist-info}/licenses/LICENSE +0 -0
- {codegraphcontext-0.4.12.dist-info → codegraphcontext-0.4.14.dist-info}/top_level.txt +0 -0
codegraphcontext/api/router.py
CHANGED
|
@@ -31,6 +31,7 @@ DEFAULT_CONFIG = {
|
|
|
31
31
|
"FALKORDB_PATH": str(CONFIG_DIR / "global" / "db" / "falkordb"),
|
|
32
32
|
"FALKORDB_SOCKET_PATH": str(CONFIG_DIR / "global" / "db" / "falkordb.sock"),
|
|
33
33
|
"LADYBUGDB_PATH": str(CONFIG_DIR / "global" / "db" / "ladybugdb"),
|
|
34
|
+
"KUZUDB_PATH": str(CONFIG_DIR / "global" / "db" / "kuzudb"),
|
|
34
35
|
"INDEX_VARIABLES": "true",
|
|
35
36
|
"ALLOW_DB_DELETION": "false",
|
|
36
37
|
"DEBUG_LOGS": "false",
|
|
@@ -72,6 +73,7 @@ CONFIG_DESCRIPTIONS = {
|
|
|
72
73
|
"FALKORDB_PATH": "Path to FalkorDB database file",
|
|
73
74
|
"FALKORDB_SOCKET_PATH": "Path to FalkorDB Unix socket",
|
|
74
75
|
"LADYBUGDB_PATH": "Path to LadybugDB database directory",
|
|
76
|
+
"KUZUDB_PATH": "Path to KuzuDB database directory",
|
|
75
77
|
"INDEX_VARIABLES": "Index variable nodes in the graph (lighter graph if false)",
|
|
76
78
|
"ALLOW_DB_DELETION": "Allow full database deletion commands",
|
|
77
79
|
"DEBUG_LOGS": "Enable debug logging (for development/troubleshooting)",
|
|
@@ -232,7 +234,7 @@ def load_config() -> Dict[str, str]:
|
|
|
232
234
|
# Load global config
|
|
233
235
|
if CONFIG_FILE.exists():
|
|
234
236
|
try:
|
|
235
|
-
with open(CONFIG_FILE, "r") as f:
|
|
237
|
+
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
|
|
236
238
|
for line in f:
|
|
237
239
|
line = line.strip()
|
|
238
240
|
if line and not line.startswith("#") and "=" in line:
|
|
@@ -245,7 +247,7 @@ def load_config() -> Dict[str, str]:
|
|
|
245
247
|
local_env = find_local_env()
|
|
246
248
|
if local_env and local_env.exists():
|
|
247
249
|
try:
|
|
248
|
-
with open(local_env, "r") as f:
|
|
250
|
+
with open(local_env, "r", encoding="utf-8") as f:
|
|
249
251
|
for line in f:
|
|
250
252
|
line = line.strip()
|
|
251
253
|
if line and not line.startswith("#") and "=" in line:
|
|
@@ -319,7 +321,7 @@ def save_config(config: Dict[str, str], preserve_db_credentials: bool = True):
|
|
|
319
321
|
if preserve_db_credentials and CONFIG_FILE.exists():
|
|
320
322
|
# Load existing credentials from file to preserve them
|
|
321
323
|
try:
|
|
322
|
-
with open(CONFIG_FILE, "r") as f:
|
|
324
|
+
with open(CONFIG_FILE, "r", encoding="utf-8") as f:
|
|
323
325
|
for line in f:
|
|
324
326
|
line = line.strip()
|
|
325
327
|
if line and not line.startswith("#") and "=" in line:
|
|
@@ -340,7 +342,7 @@ def save_config(config: Dict[str, str], preserve_db_credentials: bool = True):
|
|
|
340
342
|
credentials_to_write[key] = config[key]
|
|
341
343
|
|
|
342
344
|
try:
|
|
343
|
-
with open(CONFIG_FILE, "w") as f:
|
|
345
|
+
with open(CONFIG_FILE, "w", encoding="utf-8") as f:
|
|
344
346
|
f.write("# CodeGraphContext Configuration\n")
|
|
345
347
|
f.write(f"# Location: {CONFIG_FILE}\n\n")
|
|
346
348
|
|
|
@@ -454,7 +456,7 @@ def validate_config_value(key: str, value: str) -> tuple[bool, Optional[str]]:
|
|
|
454
456
|
except Exception as e:
|
|
455
457
|
return False, f"Cannot create log directory: {e}"
|
|
456
458
|
|
|
457
|
-
if key in ("FALKORDB_PATH", "FALKORDB_SOCKET_PATH", "LADYBUGDB_PATH"):
|
|
459
|
+
if key in ("FALKORDB_PATH", "FALKORDB_SOCKET_PATH", "LADYBUGDB_PATH", "KUZUDB_PATH"):
|
|
458
460
|
# Validate path is writable
|
|
459
461
|
db_path = Path(normalize_config_path(value, absolute=True))
|
|
460
462
|
try:
|
|
@@ -694,7 +696,7 @@ def load_context_config() -> ContextConfig:
|
|
|
694
696
|
return cfg
|
|
695
697
|
|
|
696
698
|
try:
|
|
697
|
-
with open(CONTEXT_CONFIG_FILE, "r") as f:
|
|
699
|
+
with open(CONTEXT_CONFIG_FILE, "r", encoding="utf-8") as f:
|
|
698
700
|
raw = yaml.safe_load(f) or {}
|
|
699
701
|
|
|
700
702
|
contexts: Dict[str, ContextInfo] = {}
|
|
@@ -744,7 +746,7 @@ def save_context_config(cfg: ContextConfig) -> None:
|
|
|
744
746
|
}
|
|
745
747
|
|
|
746
748
|
try:
|
|
747
|
-
with open(CONTEXT_CONFIG_FILE, "w") as f:
|
|
749
|
+
with open(CONTEXT_CONFIG_FILE, "w", encoding="utf-8") as f:
|
|
748
750
|
yaml.dump(raw, f, default_flow_style=False, sort_keys=False)
|
|
749
751
|
except Exception as e:
|
|
750
752
|
console.print(f"[red]Error saving config.yaml: {e}[/red]")
|
|
@@ -836,7 +838,7 @@ def resolve_context(
|
|
|
836
838
|
local_db = "falkordb"
|
|
837
839
|
if local_yaml.exists():
|
|
838
840
|
try:
|
|
839
|
-
with open(local_yaml) as f:
|
|
841
|
+
with open(local_yaml, encoding="utf-8") as f:
|
|
840
842
|
local_raw = yaml.safe_load(f) or {}
|
|
841
843
|
local_db = local_raw.get("database", "falkordb")
|
|
842
844
|
except Exception:
|
|
@@ -1051,7 +1053,7 @@ def discover_child_contexts(
|
|
|
1051
1053
|
local_yaml = candidate / "config.yaml"
|
|
1052
1054
|
if local_yaml.exists():
|
|
1053
1055
|
try:
|
|
1054
|
-
with open(local_yaml) as f:
|
|
1056
|
+
with open(local_yaml, encoding="utf-8") as f:
|
|
1055
1057
|
raw = yaml.safe_load(f) or {}
|
|
1056
1058
|
local_db = raw.get("database", "falkordb")
|
|
1057
1059
|
except Exception:
|
|
@@ -1080,7 +1082,7 @@ def _load_workspace_mappings() -> Dict[str, Dict[str, str]]:
|
|
|
1080
1082
|
if not CONTEXT_CONFIG_FILE.exists():
|
|
1081
1083
|
return {}
|
|
1082
1084
|
try:
|
|
1083
|
-
with open(CONTEXT_CONFIG_FILE, "r") as f:
|
|
1085
|
+
with open(CONTEXT_CONFIG_FILE, "r", encoding="utf-8") as f:
|
|
1084
1086
|
raw = yaml.safe_load(f) or {}
|
|
1085
1087
|
return raw.get("workspace_mappings", {}) or {}
|
|
1086
1088
|
except Exception:
|
|
@@ -1094,13 +1096,13 @@ def _save_workspace_mappings(mappings: Dict[str, Dict[str, str]]) -> None:
|
|
|
1094
1096
|
raw: Dict[str, Any] = {}
|
|
1095
1097
|
if CONTEXT_CONFIG_FILE.exists():
|
|
1096
1098
|
try:
|
|
1097
|
-
with open(CONTEXT_CONFIG_FILE, "r") as f:
|
|
1099
|
+
with open(CONTEXT_CONFIG_FILE, "r", encoding="utf-8") as f:
|
|
1098
1100
|
raw = yaml.safe_load(f) or {}
|
|
1099
1101
|
except Exception:
|
|
1100
1102
|
raw = {}
|
|
1101
1103
|
raw["workspace_mappings"] = mappings
|
|
1102
1104
|
try:
|
|
1103
|
-
with open(CONTEXT_CONFIG_FILE, "w") as f:
|
|
1105
|
+
with open(CONTEXT_CONFIG_FILE, "w", encoding="utf-8") as f:
|
|
1104
1106
|
yaml.dump(raw, f, default_flow_style=False, sort_keys=False)
|
|
1105
1107
|
except Exception as e:
|
|
1106
1108
|
console.print(f"[red]Error saving workspace mappings: {e}[/red]")
|
|
@@ -1122,7 +1124,7 @@ def save_workspace_mapping(cwd: Path, context_path: Path) -> None:
|
|
|
1122
1124
|
local_yaml = context_path / "config.yaml"
|
|
1123
1125
|
if local_yaml.exists():
|
|
1124
1126
|
try:
|
|
1125
|
-
with open(local_yaml) as f:
|
|
1127
|
+
with open(local_yaml, encoding="utf-8") as f:
|
|
1126
1128
|
raw = yaml.safe_load(f) or {}
|
|
1127
1129
|
local_db = raw.get("database", "falkordb")
|
|
1128
1130
|
except Exception:
|
codegraphcontext/cli/main.py
CHANGED
|
@@ -22,7 +22,6 @@ from pathlib import Path
|
|
|
22
22
|
from importlib.metadata import version as pkg_version, PackageNotFoundError
|
|
23
23
|
|
|
24
24
|
from codegraphcontext.server import MCPServer
|
|
25
|
-
from codegraphcontext.core.database import DatabaseManager
|
|
26
25
|
from .setup_wizard import run_neo4j_setup_wizard, configure_mcp_client
|
|
27
26
|
from . import config_manager
|
|
28
27
|
# Import the new helper functions
|
|
@@ -108,7 +107,7 @@ def mcp_setup():
|
|
|
108
107
|
Configure MCP Client (IDE/CLI Integration).
|
|
109
108
|
|
|
110
109
|
Sets up CodeGraphContext integration with your IDE or CLI tool:
|
|
111
|
-
- VS Code, Cursor, Windsurf
|
|
110
|
+
- VS Code, Cursor, Windsurf, Zed
|
|
112
111
|
- Claude Desktop, Gemini CLI
|
|
113
112
|
- Cline, RooCode, Amazon Q Developer, Goose
|
|
114
113
|
- OpenCode (prints stdio config + link to vendor docs)
|
|
@@ -125,7 +124,7 @@ def mcp_start():
|
|
|
125
124
|
Start the CodeGraphContext MCP server.
|
|
126
125
|
|
|
127
126
|
Starts the server which listens for JSON-RPC requests from stdin.
|
|
128
|
-
This is used by IDE integrations (VS Code, Cursor, etc.).
|
|
127
|
+
This is used by IDE integrations (VS Code, Cursor, Zed, etc.).
|
|
129
128
|
"""
|
|
130
129
|
console.print("[bold green]Starting CodeGraphContext Server...[/bold green]")
|
|
131
130
|
_load_credentials()
|
|
@@ -250,7 +249,7 @@ def context_list():
|
|
|
250
249
|
@context_app.command("create")
|
|
251
250
|
def context_create(
|
|
252
251
|
name: str = typer.Argument(..., help="Name of the new context"),
|
|
253
|
-
database: str = typer.Option(None, "--database", "-d", help="Database backend (falkordb, kuzudb, neo4j). Defaults to DEFAULT_DATABASE from config."),
|
|
252
|
+
database: str = typer.Option(None, "--database", "--db", "-db", "-d", help="Database backend (falkordb, kuzudb, neo4j). Defaults to DEFAULT_DATABASE from config."),
|
|
254
253
|
db_path: str = typer.Option(None, "--db-path", help="Explicit path for the DB (defaults to ~/.codegraphcontext/contexts/<name>/db)"),
|
|
255
254
|
):
|
|
256
255
|
"""Create a new logical context."""
|
|
@@ -291,17 +290,14 @@ def _load_credentials(cli_context_flag: Optional[str] = None):
|
|
|
291
290
|
Uses per-variable precedence - each variable is loaded from the highest priority source.
|
|
292
291
|
Priority order (highest to lowest):
|
|
293
292
|
1. Runtime environment variables (shell/CI)
|
|
294
|
-
2. Local `.env` in project directory (project-specific overrides)
|
|
293
|
+
2. Local `.codegraphcontext/.env` and `.env` in the current project directory (project-specific overrides)
|
|
295
294
|
3. Global `~/.codegraphcontext/.env` (user defaults, including `cgc config set`)
|
|
296
295
|
4. Local `mcp.json` env vars (project defaults)
|
|
297
|
-
1. Local `mcp.json` env vars (highest - explicit MCP server config)
|
|
298
|
-
2. ``<cwd>/.codegraphcontext/.env`` only (no parent-directory walk)
|
|
299
|
-
3. Global `~/.codegraphcontext/.env` (lowest - user defaults)
|
|
300
296
|
|
|
301
|
-
|
|
302
|
-
Arbitrary
|
|
297
|
+
Duplicate loading is skipped when the local file resolves to the same path as the global file.
|
|
298
|
+
Arbitrary parent directory `.env` files are not loaded—ensuring isolation.
|
|
303
299
|
"""
|
|
304
|
-
from dotenv import dotenv_values
|
|
300
|
+
from dotenv import dotenv_values
|
|
305
301
|
from codegraphcontext.cli.config_manager import (
|
|
306
302
|
ensure_config_dir,
|
|
307
303
|
codegraphcontext_dotenv_at_cwd,
|
|
@@ -360,12 +356,12 @@ def _load_credentials(cli_context_flag: Optional[str] = None):
|
|
|
360
356
|
except Exception as e:
|
|
361
357
|
console.print(f"[yellow]Warning: Could not load global .env: {e}[/yellow]")
|
|
362
358
|
|
|
363
|
-
# 2. Local project .env (project-specific overrides)
|
|
359
|
+
# 2. Local project .env (project-specific overrides - restricted to CWD only, no parent walk)
|
|
364
360
|
try:
|
|
365
|
-
|
|
366
|
-
if
|
|
367
|
-
with open(
|
|
368
|
-
_append_source(str(
|
|
361
|
+
local_dot_env = Path.cwd() / ".env"
|
|
362
|
+
if local_dot_env.exists() and local_dot_env.resolve() != global_env_path.resolve():
|
|
363
|
+
with open(local_dot_env, "r", encoding="utf-8", errors="replace") as f:
|
|
364
|
+
_append_source(str(local_dot_env), dotenv_values(stream=f))
|
|
369
365
|
except Exception as e:
|
|
370
366
|
console.print(f"[yellow]Warning: Could not load .env from current directory: {e}[/yellow]")
|
|
371
367
|
|
|
@@ -637,7 +633,7 @@ def bundle_export(
|
|
|
637
633
|
if repo_path:
|
|
638
634
|
console.print(f"[dim]Repository: {repo_path}[/dim]")
|
|
639
635
|
else:
|
|
640
|
-
console.print(
|
|
636
|
+
console.print("[dim]Exporting all repositories[/dim]")
|
|
641
637
|
|
|
642
638
|
bundle = CGCBundle(db_manager)
|
|
643
639
|
success, message = bundle.export_to_bundle(
|
|
@@ -748,7 +744,7 @@ def bundle_load(
|
|
|
748
744
|
|
|
749
745
|
# Try to download from registry
|
|
750
746
|
console.print(f"[yellow]Bundle '{bundle_name}' not found locally.[/yellow]")
|
|
751
|
-
console.print(
|
|
747
|
+
console.print("[cyan]Attempting to download from registry...[/cyan]")
|
|
752
748
|
|
|
753
749
|
try:
|
|
754
750
|
from .registry_commands import download_bundle
|
|
@@ -768,7 +764,7 @@ def bundle_load(
|
|
|
768
764
|
|
|
769
765
|
except Exception as e:
|
|
770
766
|
console.print(f"[bold red]Error: {e}[/bold red]")
|
|
771
|
-
console.print(
|
|
767
|
+
console.print("[dim]Use 'cgc registry list' to see available bundles[/dim]")
|
|
772
768
|
raise typer.Exit(code=1)
|
|
773
769
|
|
|
774
770
|
# Shortcut commands at root level
|
|
@@ -888,7 +884,7 @@ def registry_download(
|
|
|
888
884
|
bundle_path = download_bundle(name, output_dir, auto_load=load)
|
|
889
885
|
|
|
890
886
|
if load and bundle_path:
|
|
891
|
-
console.print(
|
|
887
|
+
console.print("\n[cyan]Loading bundle...[/cyan]")
|
|
892
888
|
bundle_import(bundle_path, clear=False)
|
|
893
889
|
|
|
894
890
|
@registry_app.command("request")
|
|
@@ -941,13 +937,13 @@ def doctor():
|
|
|
941
937
|
if config_manager.CONFIG_FILE.exists():
|
|
942
938
|
console.print(f" [green]✓[/green] Config loaded from {config_manager.CONFIG_FILE}")
|
|
943
939
|
else:
|
|
944
|
-
console.print(
|
|
940
|
+
console.print(" [yellow]ℹ[/yellow] No .env config found, using defaults")
|
|
945
941
|
console.print(f" [dim]Config will be created at: {config_manager.CONFIG_FILE}[/dim]")
|
|
946
942
|
|
|
947
943
|
if config_manager.CONTEXT_CONFIG_FILE.exists():
|
|
948
944
|
console.print(f" [green]✓[/green] Context config loaded from {config_manager.CONTEXT_CONFIG_FILE}")
|
|
949
945
|
else:
|
|
950
|
-
console.print(
|
|
946
|
+
console.print(" [yellow]ℹ[/yellow] No Context config found")
|
|
951
947
|
console.print(f" [dim]Context config will be auto-generated at: {config_manager.CONTEXT_CONFIG_FILE}[/dim]")
|
|
952
948
|
|
|
953
949
|
# Validate each config value
|
|
@@ -958,12 +954,12 @@ def doctor():
|
|
|
958
954
|
invalid_configs.append(f"{key}: {error_msg}")
|
|
959
955
|
|
|
960
956
|
if invalid_configs:
|
|
961
|
-
console.print(
|
|
957
|
+
console.print(" [red]✗[/red] Invalid configuration values found:")
|
|
962
958
|
for err in invalid_configs:
|
|
963
959
|
console.print(f" - {err}")
|
|
964
960
|
all_checks_passed = False
|
|
965
961
|
else:
|
|
966
|
-
console.print(
|
|
962
|
+
console.print(" [green]✓[/green] All configuration values are valid")
|
|
967
963
|
except Exception as e:
|
|
968
964
|
console.print(f" [red]✗[/red] Configuration error: {e}")
|
|
969
965
|
all_checks_passed = False
|
|
@@ -982,6 +978,7 @@ def doctor():
|
|
|
982
978
|
password = os.environ.get("NEO4J_PASSWORD")
|
|
983
979
|
database_name = os.environ.get("NEO4J_DATABASE")
|
|
984
980
|
|
|
981
|
+
from codegraphcontext.core.database import DatabaseManager
|
|
985
982
|
missing = DatabaseManager.get_missing_credentials(uri, username, password)
|
|
986
983
|
console.print(f" [cyan]Credential check:[/cyan] {'OK' if not missing else 'Missing ' + ', '.join(missing)}")
|
|
987
984
|
if missing:
|
|
@@ -1003,10 +1000,10 @@ def doctor():
|
|
|
1003
1000
|
console.print(" Start Neo4j Desktop or run: docker run -d -p 7687:7687 -p 7474:7474 neo4j")
|
|
1004
1001
|
all_checks_passed = False
|
|
1005
1002
|
|
|
1006
|
-
console.print(
|
|
1003
|
+
console.print(" [cyan]Testing Neo4j authentication/query...[/cyan]")
|
|
1007
1004
|
is_connected, error_msg = DatabaseManager.test_connection(uri, username, password, database=database_name)
|
|
1008
1005
|
if is_connected:
|
|
1009
|
-
console.print(
|
|
1006
|
+
console.print(" [green]✓[/green] Neo4j connection successful")
|
|
1010
1007
|
else:
|
|
1011
1008
|
console.print(f" [red]✗[/red] Neo4j connection failed (source: {db_source})")
|
|
1012
1009
|
console.print(f" Reason: {error_msg}")
|
|
@@ -1015,28 +1012,28 @@ def doctor():
|
|
|
1015
1012
|
from importlib.util import find_spec
|
|
1016
1013
|
|
|
1017
1014
|
if find_spec("kuzu") is not None:
|
|
1018
|
-
console.print(
|
|
1015
|
+
console.print(" [green]✓[/green] KuzuDB is installed")
|
|
1019
1016
|
else:
|
|
1020
|
-
console.print(
|
|
1021
|
-
console.print(
|
|
1017
|
+
console.print(" [red]✗[/red] KuzuDB is not installed")
|
|
1018
|
+
console.print(" Run: pip install kuzu")
|
|
1022
1019
|
all_checks_passed = False
|
|
1023
1020
|
elif default_db == "ladybugdb":
|
|
1024
1021
|
from importlib.util import find_spec
|
|
1025
1022
|
|
|
1026
1023
|
if find_spec("ladybug") is not None:
|
|
1027
|
-
console.print(
|
|
1024
|
+
console.print(" [green]✓[/green] LadybugDB core (ladybug) is installed")
|
|
1028
1025
|
else:
|
|
1029
|
-
console.print(
|
|
1030
|
-
console.print(
|
|
1026
|
+
console.print(" [red]✗[/red] LadybugDB core (ladybug) is not installed")
|
|
1027
|
+
console.print(" Run: pip install ladybug")
|
|
1031
1028
|
all_checks_passed = False
|
|
1032
1029
|
else:
|
|
1033
1030
|
# FalkorDB
|
|
1034
1031
|
try:
|
|
1035
1032
|
import falkordb
|
|
1036
|
-
console.print(
|
|
1033
|
+
console.print(" [green]✓[/green] FalkorDB Lite is installed")
|
|
1037
1034
|
except ImportError:
|
|
1038
|
-
console.print(
|
|
1039
|
-
console.print(
|
|
1035
|
+
console.print(" [yellow]⚠[/yellow] FalkorDB Lite not installed (Python 3.12+ only)")
|
|
1036
|
+
console.print(" Run: pip install falkordblite")
|
|
1040
1037
|
except Exception as e:
|
|
1041
1038
|
console.print(f" [red]✗[/red] Database check error: {e}")
|
|
1042
1039
|
all_checks_passed = False
|
|
@@ -1045,11 +1042,11 @@ def doctor():
|
|
|
1045
1042
|
console.print("\n[bold]3. Checking Tree-Sitter Installation...[/bold]")
|
|
1046
1043
|
try:
|
|
1047
1044
|
from tree_sitter import Language, Parser
|
|
1048
|
-
console.print(
|
|
1045
|
+
console.print(" [green]✓[/green] tree-sitter is installed")
|
|
1049
1046
|
|
|
1050
1047
|
try:
|
|
1051
1048
|
from tree_sitter_language_pack import get_language
|
|
1052
|
-
console.print(
|
|
1049
|
+
console.print(" [green]✓[/green] tree-sitter-language-pack is installed")
|
|
1053
1050
|
|
|
1054
1051
|
from codegraphcontext.utils.tree_sitter_manager import LANGUAGE_ALIASES, LANGUAGE_PACK_NAMES
|
|
1055
1052
|
all_langs = sorted(set(LANGUAGE_ALIASES.values()))
|
|
@@ -1067,7 +1064,7 @@ def doctor():
|
|
|
1067
1064
|
if unavailable:
|
|
1068
1065
|
console.print(f" [yellow]⚠[/yellow] Unavailable: {', '.join(unavailable)}")
|
|
1069
1066
|
except ImportError:
|
|
1070
|
-
console.print(
|
|
1067
|
+
console.print(" [red]✗[/red] tree-sitter-language-pack not installed")
|
|
1071
1068
|
all_checks_passed = False
|
|
1072
1069
|
except ImportError as e:
|
|
1073
1070
|
console.print(f" [red]✗[/red] tree-sitter not installed: {e}")
|
|
@@ -1085,12 +1082,12 @@ def doctor():
|
|
|
1085
1082
|
try:
|
|
1086
1083
|
test_file.touch()
|
|
1087
1084
|
test_file.unlink()
|
|
1088
|
-
console.print(
|
|
1085
|
+
console.print(" [green]✓[/green] Config directory is writable")
|
|
1089
1086
|
except Exception as e:
|
|
1090
1087
|
console.print(f" [red]✗[/red] Config directory not writable: {e}")
|
|
1091
1088
|
all_checks_passed = False
|
|
1092
1089
|
else:
|
|
1093
|
-
console.print(
|
|
1090
|
+
console.print(" [yellow]⚠[/yellow] Config directory doesn't exist, will be created on first use")
|
|
1094
1091
|
except Exception as e:
|
|
1095
1092
|
console.print(f" [red]✗[/red] Permission check error: {e}")
|
|
1096
1093
|
all_checks_passed = False
|
|
@@ -1102,7 +1099,7 @@ def doctor():
|
|
|
1102
1099
|
if cgc_path:
|
|
1103
1100
|
console.print(f" [green]✓[/green] cgc command found at: {cgc_path}")
|
|
1104
1101
|
else:
|
|
1105
|
-
console.print(
|
|
1102
|
+
console.print(" [yellow]⚠[/yellow] cgc command not in PATH (using python -m cgc)")
|
|
1106
1103
|
|
|
1107
1104
|
# Final summary
|
|
1108
1105
|
console.print("\n" + "=" * 60)
|
|
@@ -2393,7 +2390,7 @@ def analyze_dead_code(
|
|
|
2393
2390
|
location_str
|
|
2394
2391
|
)
|
|
2395
2392
|
|
|
2396
|
-
console.print(
|
|
2393
|
+
console.print("\n[bold yellow]⚠️ Potentially Unused Functions:[/bold yellow]")
|
|
2397
2394
|
console.print(table)
|
|
2398
2395
|
console.print(f"\n[dim]Total: {len(unused_funcs)} function(s)[/dim]")
|
|
2399
2396
|
console.print(f"[dim]Note: {results.get('note', '')}[/dim]")
|
|
@@ -11,7 +11,6 @@ from rich.table import Table
|
|
|
11
11
|
from rich.progress import Progress, SpinnerColumn, TextColumn
|
|
12
12
|
from pathlib import Path
|
|
13
13
|
from typing import Optional, List, Dict, Any
|
|
14
|
-
import time
|
|
15
14
|
|
|
16
15
|
console = Console()
|
|
17
16
|
|
|
@@ -20,7 +19,7 @@ GITHUB_REPO = "CodeGraphContext"
|
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
def fetch_available_bundles() -> List[Dict[str, Any]]:
|
|
23
|
-
"""Fetch all available bundles from
|
|
22
|
+
"""Fetch all available bundles from the Hugging Face registry (delegates to core BundleRegistry)."""
|
|
24
23
|
from ..core.bundle_registry import BundleRegistry
|
|
25
24
|
return BundleRegistry.fetch_available_bundles()
|
|
26
25
|
|
|
@@ -34,17 +33,27 @@ def _get_base_package_name(bundle_name: str) -> str:
|
|
|
34
33
|
'flask-main-abc123' -> 'flask'
|
|
35
34
|
'requests' -> 'requests'
|
|
36
35
|
"""
|
|
36
|
+
import re
|
|
37
37
|
# Remove .cgc extension if present
|
|
38
38
|
name = bundle_name.replace('.cgc', '')
|
|
39
39
|
|
|
40
|
-
#
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
|
|
40
|
+
# If the bundle name contains '-main-' or '-master-', split on that
|
|
41
|
+
for branch_indicator in ('-main-', '-master-'):
|
|
42
|
+
if branch_indicator in name:
|
|
43
|
+
return name.split(branch_indicator)[0]
|
|
44
|
+
|
|
45
|
+
# Try matching standard trailing branch and commit hash pattern
|
|
46
|
+
# e.g., -[branch]-[commit_hash] where commit_hash is a hex string
|
|
47
|
+
match = re.search(r'-(?:main|master|dev|development|release)-[a-fA-F0-9]{7,40}$', name)
|
|
48
|
+
if match:
|
|
49
|
+
return name[:match.start()]
|
|
50
|
+
|
|
51
|
+
# Try matching generic trailing branch and 7-8 char hex commit hash
|
|
52
|
+
match_generic = re.search(r'-([a-zA-Z0-9_]+)-([a-fA-F0-9]{7,8})$', name)
|
|
53
|
+
if match_generic:
|
|
54
|
+
return name[:match_generic.start()]
|
|
55
|
+
|
|
56
|
+
return name
|
|
48
57
|
|
|
49
58
|
|
|
50
59
|
def list_bundles(verbose: bool = False, unique: bool = False):
|
|
@@ -168,6 +177,8 @@ def download_bundle(name: str, output_dir: Optional[str] = None, auto_load: bool
|
|
|
168
177
|
and base names (e.g., 'python-bitcoin-utils' - picks most recent version).
|
|
169
178
|
"""
|
|
170
179
|
console.print(f"[cyan]Looking for bundle '{name}'...[/cyan]")
|
|
180
|
+
|
|
181
|
+
lookup_name = name[:-4] if name.lower().endswith('.cgc') else name
|
|
171
182
|
|
|
172
183
|
bundles = fetch_available_bundles()
|
|
173
184
|
|
|
@@ -178,7 +189,7 @@ def download_bundle(name: str, output_dir: Optional[str] = None, auto_load: bool
|
|
|
178
189
|
# Strategy 1: Try exact match on full_name (with version)
|
|
179
190
|
bundle = None
|
|
180
191
|
for b in bundles:
|
|
181
|
-
if b.get('full_name', '').lower() ==
|
|
192
|
+
if b.get('full_name', '').lower() == lookup_name.lower():
|
|
182
193
|
bundle = b
|
|
183
194
|
console.print(f"[dim]Found exact match: {b.get('full_name')}[/dim]")
|
|
184
195
|
break
|
|
@@ -188,7 +199,7 @@ def download_bundle(name: str, output_dir: Optional[str] = None, auto_load: bool
|
|
|
188
199
|
if not bundle:
|
|
189
200
|
matching_bundles = []
|
|
190
201
|
for b in bundles:
|
|
191
|
-
if b.get('name', '').lower() ==
|
|
202
|
+
if b.get('name', '').lower() == lookup_name.lower():
|
|
192
203
|
matching_bundles.append(b)
|
|
193
204
|
|
|
194
205
|
if matching_bundles:
|
|
@@ -200,7 +211,7 @@ def download_bundle(name: str, output_dir: Optional[str] = None, auto_load: bool
|
|
|
200
211
|
console.print(f"[cyan] → {bundle.get('full_name')}[/cyan]")
|
|
201
212
|
|
|
202
213
|
if len(matching_bundles) > 1:
|
|
203
|
-
console.print(
|
|
214
|
+
console.print("\n[dim]Other available versions:[/dim]")
|
|
204
215
|
for b in matching_bundles[1:4]: # Show up to 3 alternatives
|
|
205
216
|
console.print(f"[dim] • {b.get('full_name')}[/dim]")
|
|
206
217
|
if len(matching_bundles) > 4:
|
|
@@ -211,7 +222,7 @@ def download_bundle(name: str, output_dir: Optional[str] = None, auto_load: bool
|
|
|
211
222
|
if not bundle:
|
|
212
223
|
# Find bundles with similar base names
|
|
213
224
|
suggestions = []
|
|
214
|
-
name_lower =
|
|
225
|
+
name_lower = lookup_name.lower()
|
|
215
226
|
for b in bundles:
|
|
216
227
|
base_name = b.get('name', '').lower()
|
|
217
228
|
full_name = b.get('full_name', '').lower()
|
|
@@ -253,7 +264,7 @@ def download_bundle(name: str, output_dir: Optional[str] = None, auto_load: bool
|
|
|
253
264
|
if not typer.confirm("Overwrite?", default=False):
|
|
254
265
|
console.print("[yellow]Download cancelled[/yellow]")
|
|
255
266
|
if auto_load:
|
|
256
|
-
console.print(
|
|
267
|
+
console.print("[cyan]Using existing bundle for loading...[/cyan]")
|
|
257
268
|
return str(output_path)
|
|
258
269
|
return
|
|
259
270
|
output_path.unlink()
|
|
@@ -324,14 +335,14 @@ def request_bundle(repo_url: str, wait: bool = False):
|
|
|
324
335
|
console.print("[cyan]Please use one of these methods:[/cyan]\n")
|
|
325
336
|
|
|
326
337
|
console.print("1. [bold]Via Website (Recommended):[/bold]")
|
|
327
|
-
console.print(
|
|
338
|
+
console.print(" Visit: https://codegraphcontext.vercel.app")
|
|
328
339
|
console.print(f" Enter: {repo_url}")
|
|
329
|
-
console.print(
|
|
340
|
+
console.print(" Click 'Generate Bundle'\n")
|
|
330
341
|
|
|
331
342
|
console.print("2. [bold]Via GitHub Actions (Manual):[/bold]")
|
|
332
343
|
console.print(f" Go to: https://github.com/{GITHUB_ORG}/{GITHUB_REPO}/actions")
|
|
333
|
-
console.print(
|
|
334
|
-
console.print(
|
|
344
|
+
console.print(" Select: 'Generate Bundle On-Demand'")
|
|
345
|
+
console.print(" Click: 'Run workflow'")
|
|
335
346
|
console.print(f" Enter: {repo_url}\n")
|
|
336
347
|
|
|
337
348
|
console.print("[dim]Bundle generation typically takes 5-10 minutes.[/dim]")
|
|
@@ -92,8 +92,8 @@ def _generate_mcp_json(creds):
|
|
|
92
92
|
"disabledTools": [],
|
|
93
93
|
"disabled": False
|
|
94
94
|
},
|
|
95
|
-
"disabled": False
|
|
96
|
-
|
|
95
|
+
"disabled": False
|
|
96
|
+
|
|
97
97
|
}
|
|
98
98
|
}
|
|
99
99
|
}
|
|
@@ -256,7 +256,7 @@ def _configure_ide(mcp_config):
|
|
|
256
256
|
questions = [
|
|
257
257
|
{
|
|
258
258
|
"type": "confirm",
|
|
259
|
-
"message": "Automatically configure your IDE/CLI (VS Code, Cursor, Windsurf, Claude, Gemini, Cline, RooCode, ChatGPT Codex, Amazon Q Developer, Aider, Kiro, Goose, Antigravity, OpenCode)?",
|
|
259
|
+
"message": "Automatically configure your IDE/CLI (VS Code, Cursor, Windsurf, Zed, Claude, Gemini, Cline, RooCode, ChatGPT Codex, Amazon Q Developer, Aider, Kiro, Goose, Antigravity, OpenCode)?",
|
|
260
260
|
"name": "configure_ide",
|
|
261
261
|
"default": True,
|
|
262
262
|
}
|
|
@@ -270,7 +270,7 @@ def _configure_ide(mcp_config):
|
|
|
270
270
|
{
|
|
271
271
|
"type": "list",
|
|
272
272
|
"message": "Choose your IDE/CLI to configure:",
|
|
273
|
-
"choices": ["VS Code", "Cursor", "Windsurf", "Claude code", "Gemini CLI", "ChatGPT Codex", "Cline", "RooCode", "Amazon Q Developer", "JetBrainsAI", "Aider", "Kiro", "Goose", "Antigravity", "OpenCode", "None of the above"],
|
|
273
|
+
"choices": ["VS Code", "Cursor", "Windsurf", "Zed", "Claude code", "Gemini CLI", "ChatGPT Codex", "Cline", "RooCode", "Amazon Q Developer", "JetBrainsAI", "Aider", "Kiro", "Goose", "Antigravity", "OpenCode", "None of the above"],
|
|
274
274
|
"name": "ide_choice",
|
|
275
275
|
}
|
|
276
276
|
]
|
|
@@ -289,7 +289,7 @@ def _configure_ide(mcp_config):
|
|
|
289
289
|
)
|
|
290
290
|
return
|
|
291
291
|
|
|
292
|
-
if ide_choice in ["VS Code", "Cursor", "Windsurf", "Claude code", "Gemini CLI", "ChatGPT Codex", "Cline", "RooCode", "Amazon Q Developer", "JetBrainsAI", "Aider", "Kiro", "Goose", "Antigravity"]:
|
|
292
|
+
if ide_choice in ["VS Code", "Cursor", "Windsurf", "Zed", "Claude code", "Gemini CLI", "ChatGPT Codex", "Cline", "RooCode", "Amazon Q Developer", "JetBrainsAI", "Aider", "Kiro", "Goose", "Antigravity"]:
|
|
293
293
|
console.print(f"\n[bold cyan]Configuring for {ide_choice}...[/bold cyan]")
|
|
294
294
|
|
|
295
295
|
if ide_choice == "Amazon Q Developer":
|
|
@@ -320,6 +320,10 @@ def _configure_ide(mcp_config):
|
|
|
320
320
|
Path.home() / "AppData" / "Roaming" / "windsurf" / "settings.json",
|
|
321
321
|
Path.home() / ".config" / "Windsurf" / "User" / "settings.json",
|
|
322
322
|
],
|
|
323
|
+
"Zed": [
|
|
324
|
+
Path.home() / ".config" / "zed" / "settings.json",
|
|
325
|
+
Path.home() / "AppData" / "Roaming" / "Zed" / "settings.json"
|
|
326
|
+
],
|
|
323
327
|
"Claude code": [
|
|
324
328
|
Path.home() / ".claude.json"
|
|
325
329
|
],
|
|
@@ -398,10 +402,14 @@ def _configure_ide(mcp_config):
|
|
|
398
402
|
console.print(f"[red]Error: Configuration file at {target_path} is not a valid JSON object.[/red]")
|
|
399
403
|
return
|
|
400
404
|
|
|
401
|
-
if "
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
+
if ide_choice == "Zed":
|
|
406
|
+
if "context_servers" not in settings:
|
|
407
|
+
settings["context_servers"] = {}
|
|
408
|
+
settings["context_servers"].update(mcp_config["mcpServers"])
|
|
409
|
+
else:
|
|
410
|
+
if "mcpServers" not in settings:
|
|
411
|
+
settings["mcpServers"] = {}
|
|
412
|
+
settings["mcpServers"].update(mcp_config["mcpServers"])
|
|
405
413
|
|
|
406
414
|
try:
|
|
407
415
|
with open(target_path, "w") as f:
|
|
@@ -677,6 +685,7 @@ def setup_existing_db():
|
|
|
677
685
|
|
|
678
686
|
# Validate the user input
|
|
679
687
|
console.print("\n[cyan]🔍 Validating configuration...[/cyan]")
|
|
688
|
+
from codegraphcontext.core.database import DatabaseManager
|
|
680
689
|
is_valid, validation_error = DatabaseManager.validate_config(
|
|
681
690
|
manual_creds.get("uri", ""),
|
|
682
691
|
manual_creds.get("username", ""),
|
|
@@ -795,6 +804,7 @@ def setup_hosted_db():
|
|
|
795
804
|
|
|
796
805
|
# Validate the user input
|
|
797
806
|
console.print("\n[cyan]🔍 Validating configuration...[/cyan]")
|
|
807
|
+
from codegraphcontext.core.database import DatabaseManager
|
|
798
808
|
is_valid, validation_error = DatabaseManager.validate_config(
|
|
799
809
|
manual_creds.get("uri", ""),
|
|
800
810
|
manual_creds.get("username", ""),
|
|
@@ -913,6 +923,7 @@ volumes:
|
|
|
913
923
|
|
|
914
924
|
# Validate configuration format before attempting Docker operations
|
|
915
925
|
console.print("\n[cyan]🔍 Validating configuration...[/cyan]")
|
|
926
|
+
from codegraphcontext.core.database import DatabaseManager
|
|
916
927
|
is_valid, validation_error = DatabaseManager.validate_config(
|
|
917
928
|
DEFAULT_NEO4J_URI,
|
|
918
929
|
DEFAULT_NEO4J_USERNAME,
|
|
@@ -972,6 +983,7 @@ volumes:
|
|
|
972
983
|
|
|
973
984
|
# updated test_connection method
|
|
974
985
|
console.print(f"[yellow]Testing connection... (attempt {attempt + 1}/{max_attempts})[/yellow]")
|
|
986
|
+
from codegraphcontext.core.database import DatabaseManager
|
|
975
987
|
is_connected, error_msg = DatabaseManager.test_connection(DEFAULT_NEO4J_URI, DEFAULT_NEO4J_USERNAME, password)
|
|
976
988
|
|
|
977
989
|
if is_connected:
|