codegraphcontext 0.4.14__py3-none-any.whl → 0.4.16__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.
@@ -34,6 +34,22 @@ from .config_manager import resolve_context, ResolvedContext, register_repo_in_c
34
34
  console = Console()
35
35
 
36
36
 
37
+ def _fail_services_init() -> None:
38
+ """Abort the CLI command when database/services could not be initialized."""
39
+ raise typer.Exit(code=1)
40
+
41
+
42
+ def _kuzu_fallback_path(ctx: ResolvedContext) -> Optional[str]:
43
+ """Derive a KùzuDB directory when falling back from another backend."""
44
+ if ctx.db_path:
45
+ return str(Path(ctx.db_path).parent / "kuzudb")
46
+ try:
47
+ from .config_manager import _default_global_db_path
48
+ return _default_global_db_path("kuzudb")
49
+ except Exception:
50
+ return None
51
+
52
+
37
53
  def _print_call_resolution_diagnostics(graph_builder: GraphBuilder, limit: int = 5) -> None:
38
54
  diagnostics = getattr(graph_builder, "last_call_resolution_diagnostics", [])
39
55
  if not diagnostics:
@@ -59,14 +75,17 @@ def _print_call_resolution_diagnostics(graph_builder: GraphBuilder, limit: int =
59
75
  console.print(table)
60
76
 
61
77
 
62
- def _initialize_services(cli_context_flag: Optional[str] = None) -> tuple[Any, Any, Any, ResolvedContext]:
78
+ def _initialize_services(
79
+ cli_context_flag: Optional[str] = None,
80
+ cwd: Optional[Path] = None,
81
+ ) -> tuple[Any, Any, Any, ResolvedContext]:
63
82
  """
64
83
  Initializes and returns core service managers based on the resolved context.
65
84
  Returns (db_manager, graph_builder, code_finder, resolved_context).
66
85
  """
67
86
  ensure_first_run_bootstrap()
68
87
  console.print("[dim]Resolving context...[/dim]")
69
- ctx = resolve_context(cli_context_flag)
88
+ ctx = resolve_context(cli_context_flag, cwd=cwd)
70
89
 
71
90
  # Let the user know what context we're operating in
72
91
  if ctx.mode == "named":
@@ -93,7 +112,7 @@ def _initialize_services(cli_context_flag: Optional[str] = None) -> tuple[Any, A
93
112
  db_manager = get_database_manager(db_path=runtime_path or ctx.db_path)
94
113
  except ValueError as e:
95
114
  console.print(f"[bold red]Database Configuration Error:[/bold red] {e}")
96
- return None, None, None, ctx
115
+ _fail_services_init()
97
116
 
98
117
  try:
99
118
  db_manager.get_driver()
@@ -110,15 +129,16 @@ def _initialize_services(cli_context_flag: Optional[str] = None) -> tuple[Any, A
110
129
  except Exception:
111
130
  pass
112
131
 
113
- # Re-initialize explicitly with KùzuDB
132
+ # Re-initialize explicitly with KùzuDB (never reuse the FalkorDB directory)
114
133
  from ..core.database_kuzu import KuzuDBManager
115
- db_manager = KuzuDBManager()
134
+ kuzu_path = _kuzu_fallback_path(ctx)
135
+ db_manager = KuzuDBManager(db_path=kuzu_path)
116
136
  try:
117
137
  db_manager.get_driver()
118
138
  console.print("[green]✓[/green] Successfully switched to KùzuDB fallback")
119
139
  except Exception as kuzu_e:
120
140
  console.print(f"[bold red]Critical Error:[/bold red] Both FalkorDB and KùzuDB failed: {kuzu_e}")
121
- return None, None, None, ctx
141
+ _fail_services_init()
122
142
  else:
123
143
  selected_db = (
124
144
  os.environ.get("CGC_RUNTIME_DB_TYPE")
@@ -135,20 +155,20 @@ def _initialize_services(cli_context_flag: Optional[str] = None) -> tuple[Any, A
135
155
  console.print("[cyan]Neo4j failed and CGC_ALLOW_NEO4J_FALLBACK=true. Falling back to KuzuDB...[/cyan]")
136
156
  try:
137
157
  from ..core.database_kuzu import KuzuDBManager
138
- db_manager = KuzuDBManager()
158
+ db_manager = KuzuDBManager(db_path=_kuzu_fallback_path(ctx))
139
159
  db_manager.get_driver()
140
160
  console.print("[green]✓[/green] Successfully switched to KuzuDB fallback")
141
161
  except Exception as kuzu_e:
142
162
  console.print(f"[bold red]Critical Error:[/bold red] Neo4j failed and KuzuDB fallback failed: {kuzu_e}")
143
- return None, None, None, ctx
163
+ _fail_services_init()
144
164
  else:
145
165
  if selected_db == "neo4j":
146
166
  console.print("[yellow]Tip:[/yellow] To continue without Neo4j, rerun with --db kuzudb")
147
- return None, None, None, ctx
167
+ _fail_services_init()
148
168
  else:
149
169
  console.print(f"[bold red]Database Connection Error:[/bold red] {e}")
150
170
  console.print("Please ensure your database is configured correctly or run 'cgc doctor'.")
151
- return None, None, None, ctx
171
+ _fail_services_init()
152
172
 
153
173
  # The GraphBuilder requires an event loop, even for synchronous-style execution
154
174
  try:
@@ -224,17 +244,18 @@ async def _run_index_with_progress(graph_builder: GraphBuilder, path_obj: Path,
224
244
  def index_helper(path: str, context: Optional[str] = None):
225
245
  """Synchronously indexes a repository in a given context."""
226
246
  time_start = time.time()
227
- services = _initialize_services(context)
247
+ path_obj = Path(path).resolve()
248
+ index_cwd = path_obj if path_obj.is_dir() else path_obj.parent
249
+ services = _initialize_services(context, cwd=index_cwd)
228
250
  if not all(services[:3]):
229
- return
251
+ _fail_services_init()
230
252
 
231
253
  db_manager, graph_builder, code_finder, ctx = services
232
- path_obj = Path(path).resolve()
233
254
 
234
255
  if not path_obj.exists():
235
256
  console.print(f"[red]Error: Path does not exist: {path_obj}[/red]")
236
257
  db_manager.close_driver()
237
- return
258
+ raise typer.Exit(code=1)
238
259
 
239
260
  indexed_repos = code_finder.list_indexed_repositories()
240
261
  repo_exists = any_repo_matches_path(indexed_repos, path_obj)
@@ -298,7 +319,7 @@ def add_package_helper(package_name: str, language: str, context: Optional[str]
298
319
  """Synchronously indexes a package."""
299
320
  services = _initialize_services(context)
300
321
  if not all(services[:3]):
301
- return
322
+ _fail_services_init()
302
323
 
303
324
  db_manager, graph_builder, code_finder, ctx = services
304
325
 
@@ -332,7 +353,7 @@ def list_repos_helper(context: Optional[str] = None):
332
353
  """Lists all indexed repositories."""
333
354
  services = _initialize_services(context)
334
355
  if not all(services[:3]):
335
- return
356
+ _fail_services_init()
336
357
 
337
358
  db_manager, _, code_finder, ctx = services
338
359
 
@@ -362,7 +383,7 @@ def delete_helper(repo_path: str, context: Optional[str] = None):
362
383
  """Deletes a repository from the graph."""
363
384
  services = _initialize_services(context)
364
385
  if not all(services[:3]):
365
- return
386
+ _fail_services_init()
366
387
 
367
388
  db_manager, graph_builder, _, ctx = services
368
389
 
@@ -382,7 +403,7 @@ def cypher_helper(query: str, context: Optional[str] = None):
382
403
  """Executes a read-only Cypher query."""
383
404
  services = _initialize_services(context)
384
405
  if not all(services[:3]):
385
- return
406
+ _fail_services_init()
386
407
 
387
408
  db_manager, _, _, ctx = services
388
409
 
@@ -393,7 +414,7 @@ def cypher_helper(query: str, context: Optional[str] = None):
393
414
  if re.search(pattern, query, re.IGNORECASE):
394
415
  console.print("[bold red]Error: This command only supports read-only queries.[/bold red]")
395
416
  db_manager.close_driver()
396
- return
417
+ raise typer.Exit(code=1)
397
418
 
398
419
  try:
399
420
  with db_manager.get_driver().session() as session:
@@ -412,7 +433,7 @@ def cypher_helper_visual(query: str, context: Optional[str] = None):
412
433
 
413
434
  services = _initialize_services(context)
414
435
  if not all(services[:3]):
415
- return
436
+ _fail_services_init()
416
437
 
417
438
  db_manager, _, _, ctx = services
418
439
 
@@ -423,7 +444,7 @@ def cypher_helper_visual(query: str, context: Optional[str] = None):
423
444
  if re.search(pattern, query, re.IGNORECASE):
424
445
  console.print("[bold red]Error: This command only supports read-only queries.[/bold red]")
425
446
  db_manager.close_driver()
426
- return
447
+ raise typer.Exit(code=1)
427
448
 
428
449
  try:
429
450
  with db_manager.get_driver().session() as session:
@@ -449,7 +470,7 @@ def visualize_helper(repo_path: Optional[str] = None, port: int = 8000, context:
449
470
  """Generates an interactive visualization using the Playground UI."""
450
471
  services = _initialize_services(context)
451
472
  if not all(services[:3]):
452
- return
473
+ _fail_services_init()
453
474
 
454
475
  db_manager, _, _, ctx = services
455
476
 
@@ -546,7 +567,7 @@ def reindex_helper(path: str, context: Optional[str] = None):
546
567
  time_start = time.time()
547
568
  services = _initialize_services(context)
548
569
  if not all(services[:3]):
549
- return
570
+ _fail_services_init()
550
571
 
551
572
  db_manager, graph_builder, code_finder, ctx = services
552
573
  path_obj = Path(path).resolve()
@@ -595,7 +616,7 @@ def clean_helper(context: Optional[str] = None):
595
616
  """Remove orphaned nodes and relationships from the database."""
596
617
  services = _initialize_services(context)
597
618
  if not all(services[:3]):
598
- return
619
+ _fail_services_init()
599
620
 
600
621
  db_manager, _, _, ctx = services
601
622
 
@@ -643,7 +664,7 @@ def stats_helper(path: str = None, context: Optional[str] = None):
643
664
  """Show indexing statistics for a repository or overall."""
644
665
  services = _initialize_services(context)
645
666
  if not all(services[:3]):
646
- return
667
+ _fail_services_init()
647
668
 
648
669
  db_manager, _, code_finder, ctx = services
649
670
 
@@ -753,7 +774,7 @@ def watch_helper(path: str, context: Optional[str] = None):
753
774
 
754
775
  services = _initialize_services(context)
755
776
  if not all(services[:3]):
756
- return
777
+ _fail_services_init()
757
778
 
758
779
  db_manager, graph_builder, code_finder, ctx = services
759
780
  path_obj = Path(path).resolve()
@@ -19,10 +19,17 @@ console = Console()
19
19
  CONFIG_DIR = Path.home() / ".codegraphcontext"
20
20
  CONFIG_FILE = CONFIG_DIR / ".env"
21
21
 
22
+ # Keys that pin embedded DB directories; must not bleed across profiles via local .env
23
+ DB_PATH_ENV_KEYS = frozenset({
24
+ "FALKORDB_PATH", "FALKORDB_SOCKET_PATH", "KUZUDB_PATH", "LADYBUGDB_PATH",
25
+ })
26
+
22
27
  # Database credential keys (stored in same .env file but not managed as config)
23
28
  DATABASE_CREDENTIAL_KEYS = {
24
29
  "NEO4J_URI", "NEO4J_USERNAME", "NEO4J_PASSWORD", "NEO4J_DATABASE",
25
- "NORNIC_URI", "NORNIC_USERNAME", "NORNIC_PASSWORD", "NORNIC_DATABASE"
30
+ "NORNIC_URI", "NORNIC_USERNAME", "NORNIC_PASSWORD", "NORNIC_DATABASE",
31
+ "FALKORDB_HOST", "FALKORDB_PORT", "FALKORDB_PASSWORD", "FALKORDB_SSL",
32
+ "FALKORDB_GRAPH_NAME",
26
33
  }
27
34
 
28
35
  # Default configuration values
@@ -669,7 +676,10 @@ def _default_global_db_path(database: str) -> str:
669
676
  if database == "falkordb":
670
677
  custom_path = load_config().get("FALKORDB_PATH")
671
678
  if custom_path:
672
- return str(Path(custom_path).resolve())
679
+ resolved = Path(custom_path).resolve()
680
+ # Ignore paths from another profile/repo that leaked via local .env
681
+ if str(resolved).startswith(str(CONFIG_DIR.resolve())):
682
+ return str(resolved)
673
683
  if _LEGACY_FALKORDB_PATH.exists():
674
684
  return str(_LEGACY_FALKORDB_PATH)
675
685
  return str(CONFIG_DIR / "global" / "db" / database)
@@ -302,6 +302,7 @@ def _load_credentials(cli_context_flag: Optional[str] = None):
302
302
  ensure_config_dir,
303
303
  codegraphcontext_dotenv_at_cwd,
304
304
  normalize_config_path,
305
+ DB_PATH_ENV_KEYS,
305
306
  )
306
307
 
307
308
  # Ensure config directory exists (lazy initialization)
@@ -371,6 +372,11 @@ def _load_credentials(cli_context_flag: Optional[str] = None):
371
372
  if local_cgc_env and local_cgc_env.resolve() != global_env_path.resolve():
372
373
  with open(local_cgc_env, "r", encoding="utf-8", errors="replace") as f:
373
374
  vals = dotenv_values(stream=f)
375
+ # Do not let a repo-local profile override another user's global DB paths.
376
+ vals = {
377
+ k: v for k, v in (vals or {}).items()
378
+ if k not in DB_PATH_ENV_KEYS
379
+ }
374
380
  _append_source(str(local_cgc_env), vals)
375
381
  except Exception as e:
376
382
  console.print(
@@ -622,7 +628,8 @@ def bundle_export(
622
628
 
623
629
  services = _initialize_services(context)
624
630
  if not all(services[:3]):
625
- return
631
+ from .cli_helpers import _fail_services_init
632
+ _fail_services_init()
626
633
  db_manager, _, code_finder = services[:3]
627
634
 
628
635
  try:
@@ -655,6 +662,7 @@ def bundle_export(
655
662
  def bundle_import(
656
663
  bundle_file: str = typer.Argument(..., help="Path to the .cgc bundle file to import"),
657
664
  clear: bool = typer.Option(False, "--clear", help="Clear existing graph data before importing"),
665
+ yes: bool = typer.Option(False, "--yes", "-y", help="Skip confirmation when using --clear"),
658
666
  context: Optional[str] = typer.Option(None, "--context", "-c", help="Specific context to use"),
659
667
  ):
660
668
  """
@@ -672,7 +680,8 @@ def bundle_import(
672
680
 
673
681
  services = _initialize_services(context)
674
682
  if not all(services[:3]):
675
- return
683
+ from .cli_helpers import _fail_services_init
684
+ _fail_services_init()
676
685
  db_manager, graph_builder, code_finder = services[:3]
677
686
 
678
687
  try:
@@ -684,9 +693,9 @@ def bundle_import(
684
693
 
685
694
  if clear:
686
695
  console.print("[yellow]⚠️ Warning: This will clear all existing graph data![/yellow]")
687
- if not typer.confirm("Are you sure you want to continue?", default=False):
696
+ if not yes and not typer.confirm("Are you sure you want to continue?", default=False):
688
697
  console.print("[yellow]Import cancelled[/yellow]")
689
- return
698
+ raise typer.Exit(code=1)
690
699
 
691
700
  console.print(f"[cyan]Importing bundle from {bundle_path}...[/cyan]")
692
701
 
@@ -1026,6 +1035,26 @@ def doctor():
1026
1035
  console.print(" [red]✗[/red] LadybugDB core (ladybug) is not installed")
1027
1036
  console.print(" Run: pip install ladybug")
1028
1037
  all_checks_passed = False
1038
+ elif default_db == "falkordb-remote":
1039
+ host = os.environ.get("FALKORDB_HOST")
1040
+ if host:
1041
+ port = os.environ.get("FALKORDB_PORT", "6379")
1042
+ console.print(f" [cyan]Endpoint:[/cyan] {host}:{port}")
1043
+ try:
1044
+ from codegraphcontext.core.database_falkordb_remote import FalkorDBRemoteManager
1045
+ ok, msg = FalkorDBRemoteManager.test_connection()
1046
+ if ok:
1047
+ console.print(" [green]✓[/green] FalkorDB remote connection successful")
1048
+ else:
1049
+ console.print(f" [red]✗[/red] FalkorDB remote connection failed: {msg}")
1050
+ all_checks_passed = False
1051
+ except Exception as exc:
1052
+ console.print(f" [red]✗[/red] FalkorDB remote check error: {exc}")
1053
+ all_checks_passed = False
1054
+ else:
1055
+ console.print(" [red]✗[/red] FALKORDB_HOST is not configured")
1056
+ console.print(" Run: cgc config set FALKORDB_HOST 127.0.0.1")
1057
+ all_checks_passed = False
1029
1058
  else:
1030
1059
  # FalkorDB
1031
1060
  try:
@@ -1200,7 +1229,8 @@ def delete(
1200
1229
  # Delete all repositories
1201
1230
  services = _initialize_services(context)
1202
1231
  if not all(services[:3]):
1203
- return
1232
+ from .cli_helpers import _fail_services_init
1233
+ _fail_services_init()
1204
1234
  db_manager, graph_builder, code_finder = services[:3]
1205
1235
 
1206
1236
  try:
@@ -1435,7 +1465,8 @@ def find_by_name(
1435
1465
  _load_credentials()
1436
1466
  services = _initialize_services(context)
1437
1467
  if not all(services[:3]):
1438
- return
1468
+ from .cli_helpers import _fail_services_init
1469
+ _fail_services_init()
1439
1470
  db_manager, graph_builder, code_finder = services[:3]
1440
1471
 
1441
1472
  # Resolve effective fuzzy setting: CLI flag wins, else config, else true.
@@ -1557,7 +1588,8 @@ def find_by_pattern(
1557
1588
  _load_credentials()
1558
1589
  services = _initialize_services(context)
1559
1590
  if not all(services[:3]):
1560
- return
1591
+ from .cli_helpers import _fail_services_init
1592
+ _fail_services_init()
1561
1593
  db_manager, graph_builder, code_finder = services[:3]
1562
1594
 
1563
1595
  try:
@@ -1650,7 +1682,8 @@ def find_by_type(
1650
1682
  _load_credentials()
1651
1683
  services = _initialize_services(context)
1652
1684
  if not all(services[:3]):
1653
- return
1685
+ from .cli_helpers import _fail_services_init
1686
+ _fail_services_init()
1654
1687
  db_manager, graph_builder, code_finder = services[:3]
1655
1688
 
1656
1689
  try:
@@ -1705,7 +1738,8 @@ def find_by_variable(
1705
1738
  _load_credentials()
1706
1739
  services = _initialize_services(context)
1707
1740
  if not all(services[:3]):
1708
- return
1741
+ from .cli_helpers import _fail_services_init
1742
+ _fail_services_init()
1709
1743
  db_manager, graph_builder, code_finder = services[:3]
1710
1744
 
1711
1745
  try:
@@ -1751,7 +1785,8 @@ def find_by_content_search(
1751
1785
  _load_credentials()
1752
1786
  services = _initialize_services(context)
1753
1787
  if not all(services[:3]):
1754
- return
1788
+ from .cli_helpers import _fail_services_init
1789
+ _fail_services_init()
1755
1790
  db_manager, graph_builder, code_finder = services[:3]
1756
1791
 
1757
1792
  try:
@@ -1813,7 +1848,8 @@ def find_by_decorator_search(
1813
1848
  _load_credentials()
1814
1849
  services = _initialize_services(context)
1815
1850
  if not all(services[:3]):
1816
- return
1851
+ from .cli_helpers import _fail_services_init
1852
+ _fail_services_init()
1817
1853
  db_manager, graph_builder, code_finder = services[:3]
1818
1854
 
1819
1855
  try:
@@ -1861,7 +1897,8 @@ def find_by_argument_search(
1861
1897
  _load_credentials()
1862
1898
  services = _initialize_services(context)
1863
1899
  if not all(services[:3]):
1864
- return
1900
+ from .cli_helpers import _fail_services_init
1901
+ _fail_services_init()
1865
1902
  db_manager, graph_builder, code_finder = services[:3]
1866
1903
 
1867
1904
  try:
@@ -1917,7 +1954,8 @@ def analyze_calls(
1917
1954
  _load_credentials()
1918
1955
  services = _initialize_services(context)
1919
1956
  if not all(services[:3]):
1920
- return
1957
+ from .cli_helpers import _fail_services_init
1958
+ _fail_services_init()
1921
1959
  db_manager, graph_builder, code_finder = services[:3]
1922
1960
 
1923
1961
  try:
@@ -1973,7 +2011,8 @@ def analyze_callers(
1973
2011
  _load_credentials()
1974
2012
  services = _initialize_services(context)
1975
2013
  if not all(services[:3]):
1976
- return
2014
+ from .cli_helpers import _fail_services_init
2015
+ _fail_services_init()
1977
2016
  db_manager, graph_builder, code_finder = services[:3]
1978
2017
 
1979
2018
  try:
@@ -2034,7 +2073,8 @@ def analyze_chain(
2034
2073
  _load_credentials()
2035
2074
  services = _initialize_services(context)
2036
2075
  if not all(services[:3]):
2037
- return
2076
+ from .cli_helpers import _fail_services_init
2077
+ _fail_services_init()
2038
2078
  db_manager, graph_builder, code_finder = services[:3]
2039
2079
 
2040
2080
  try:
@@ -2104,7 +2144,8 @@ def analyze_kotlin_call_audit(
2104
2144
  _load_credentials()
2105
2145
  services = _initialize_services(context)
2106
2146
  if not all(services[:3]):
2107
- return
2147
+ from .cli_helpers import _fail_services_init
2148
+ _fail_services_init()
2108
2149
  db_manager, _, code_finder = services[:3]
2109
2150
 
2110
2151
  try:
@@ -2164,7 +2205,8 @@ def analyze_dependencies(
2164
2205
  _load_credentials()
2165
2206
  services = _initialize_services(context)
2166
2207
  if not all(services[:3]):
2167
- return
2208
+ from .cli_helpers import _fail_services_init
2209
+ _fail_services_init()
2168
2210
  db_manager, graph_builder, code_finder = services[:3]
2169
2211
 
2170
2212
  try:
@@ -2216,7 +2258,8 @@ def analyze_inheritance_tree(
2216
2258
  _load_credentials()
2217
2259
  services = _initialize_services(context)
2218
2260
  if not all(services[:3]):
2219
- return
2261
+ from .cli_helpers import _fail_services_init
2262
+ _fail_services_init()
2220
2263
  db_manager, graph_builder, code_finder = services[:3]
2221
2264
 
2222
2265
  try:
@@ -2286,7 +2329,8 @@ def analyze_complexity(
2286
2329
  _load_credentials()
2287
2330
  services = _initialize_services(context)
2288
2331
  if not all(services[:3]):
2289
- return
2332
+ from .cli_helpers import _fail_services_init
2333
+ _fail_services_init()
2290
2334
  db_manager, graph_builder, code_finder = services[:3]
2291
2335
 
2292
2336
  _FILE_EXTENSIONS = ('.py', '.js', '.ts', '.jsx', '.tsx', '.go', '.rs', '.rb',
@@ -2363,7 +2407,8 @@ def analyze_dead_code(
2363
2407
  _load_credentials()
2364
2408
  services = _initialize_services(context)
2365
2409
  if not all(services[:3]):
2366
- return
2410
+ from .cli_helpers import _fail_services_init
2411
+ _fail_services_init()
2367
2412
  db_manager, graph_builder, code_finder = services[:3]
2368
2413
 
2369
2414
  try:
@@ -2417,7 +2462,8 @@ def analyze_overrides(
2417
2462
  _load_credentials()
2418
2463
  services = _initialize_services(context)
2419
2464
  if not all(services[:3]):
2420
- return
2465
+ from .cli_helpers import _fail_services_init
2466
+ _fail_services_init()
2421
2467
  db_manager, graph_builder, code_finder = services[:3]
2422
2468
 
2423
2469
  try:
@@ -2472,7 +2518,8 @@ def analyze_variable_usage(
2472
2518
  _load_credentials()
2473
2519
  services = _initialize_services(context)
2474
2520
  if not all(services[:3]):
2475
- return
2521
+ from .cli_helpers import _fail_services_init
2522
+ _fail_services_init()
2476
2523
  db_manager, graph_builder, code_finder = services[:3]
2477
2524
 
2478
2525
  try:
@@ -2634,7 +2681,7 @@ def main(
2634
2681
  "--database",
2635
2682
  "--db",
2636
2683
  "-db",
2637
- help="[Global] Temporarily override database backend (falkordb, falkordb-remote, neo4j, or kuzudb) for any command"
2684
+ help="[Global] Temporarily override database backend (falkordb, falkordb-remote, kuzudb, ladybugdb, neo4j, or nornic) for any command"
2638
2685
  ),
2639
2686
  visual: bool = typer.Option(
2640
2687
  False,
@@ -2849,7 +2896,7 @@ def _write_datasource_graph(ingested: dict) -> None:
2849
2896
  raise typer.Exit(1)
2850
2897
 
2851
2898
  from codegraphcontext.tools.indexing.persistence.writer import GraphWriter
2852
- GraphWriter(driver).write_datasource_graph(ingested)
2899
+ GraphWriter(driver, db_manager=dm).write_datasource_graph(ingested)
2853
2900
 
2854
2901
 
2855
2902
  if __name__ == "__main__":
@@ -71,12 +71,25 @@ class CGCBundle:
71
71
  Returns:
72
72
  str: 'elementId' for Neo4j, 'id' for FalkorDB
73
73
  """
74
- # Check if we're using Neo4j or FalkorDB
75
74
  backend = self.db_manager.get_backend_type()
76
75
  if backend == 'neo4j':
77
76
  return 'elementId'
78
- else: # FalkorDB or other backends
79
- return 'id'
77
+ return 'id'
78
+
79
+ def _uses_pk_edge_matching(self) -> bool:
80
+ """Kùzu/Ladybug internal IDs are not comparable via id() in MATCH."""
81
+ return self.db_manager.get_backend_type() in {'kuzudb', 'ladybugdb'}
82
+
83
+ def _node_lookup_key(self, labels, properties: Dict) -> Optional[tuple]:
84
+ if not labels:
85
+ return None
86
+ if isinstance(labels, str):
87
+ labels = [labels]
88
+ primary_label = labels[0]
89
+ pk_field = self._PK_MAP.get(primary_label)
90
+ if pk_field and pk_field in properties:
91
+ return (primary_label, pk_field, properties[pk_field])
92
+ return None
80
93
 
81
94
 
82
95
  def export_to_bundle(
@@ -139,7 +152,7 @@ class CGCBundle:
139
152
  from importlib.metadata import version as get_version
140
153
  py_version = get_version("codegraphcontext")
141
154
  except Exception:
142
- py_version = "0.4.14"
155
+ py_version = "0.4.16"
143
156
 
144
157
  metadata["format_version"] = "1.0.0"
145
158
  metadata["generator"] = f"PYv{py_version}"
@@ -368,18 +381,24 @@ class CGCBundle:
368
381
  }
369
382
 
370
383
  with self.db_manager.get_driver().session() as session:
371
- # Get node labels
384
+ # Get node labels (backend-aware)
385
+ backend = getattr(self.db_manager, "get_backend_type", lambda: "neo4j")()
372
386
  try:
373
- result = session.run("CALL db.labels()")
374
- labels = []
375
- for record in result:
376
- try:
377
- labels.append(record[0])
378
- except (KeyError, TypeError):
379
- if hasattr(record, 'values'):
380
- vals = list(record.values())
381
- if vals:
382
- labels.append(vals[0])
387
+ if backend in ("kuzudb", "ladybugdb"):
388
+ # KuzuDB/LadybugDB: SHOW TABLES not available in ≤ 0.11
389
+ result = session.run("MATCH (n) RETURN DISTINCT label(n) AS lbl")
390
+ labels = sorted({record[0] for record in result if record[0] is not None})
391
+ else:
392
+ result = session.run("CALL db.labels()")
393
+ labels = []
394
+ for record in result:
395
+ try:
396
+ labels.append(record[0])
397
+ except (KeyError, TypeError):
398
+ if hasattr(record, 'values'):
399
+ vals = list(record.values())
400
+ if vals:
401
+ labels.append(vals[0])
383
402
  schema["node_labels"] = labels
384
403
  except Exception:
385
404
  schema["node_labels"] = []
@@ -908,7 +927,12 @@ cgc import <bundle-file>.cgc
908
927
 
909
928
  record = result.single()
910
929
  if record and old_id:
911
- id_mapping[old_id] = record['new_id']
930
+ if self._uses_pk_edge_matching():
931
+ lookup = self._node_lookup_key(labels, properties)
932
+ if lookup:
933
+ id_mapping[old_id] = lookup
934
+ else:
935
+ id_mapping[old_id] = record['new_id']
912
936
 
913
937
  return len(batch)
914
938
 
@@ -959,14 +983,27 @@ cgc import <bundle-file>.cgc
959
983
  warning_logger(f"Skipping edge: node IDs not found in mapping")
960
984
  continue
961
985
 
962
- # Create relationship
963
- query = f"""
964
- MATCH (a), (b)
965
- WHERE {id_function}(a) = $from_id AND {id_function}(b) = $to_id
966
- CREATE (a)-[r:{rel_type}]->(b)
967
- SET r = $props
968
- """
969
-
970
- session.run(query, from_id=new_from, to_id=new_to, props=properties)
986
+ if self._uses_pk_edge_matching():
987
+ from_label, from_pk, from_val = new_from
988
+ to_label, to_pk, to_val = new_to
989
+ query = f"""
990
+ MATCH (a:{from_label} {{{from_pk}: $from_val}}), (b:{to_label} {{{to_pk}: $to_val}})
991
+ CREATE (a)-[r:{rel_type}]->(b)
992
+ SET r = $props
993
+ """
994
+ session.run(
995
+ query,
996
+ from_val=from_val,
997
+ to_val=to_val,
998
+ props=properties,
999
+ )
1000
+ else:
1001
+ query = f"""
1002
+ MATCH (a), (b)
1003
+ WHERE {id_function}(a) = $from_id AND {id_function}(b) = $to_id
1004
+ CREATE (a)-[r:{rel_type}]->(b)
1005
+ SET r = $props
1006
+ """
1007
+ session.run(query, from_id=new_from, to_id=new_to, props=properties)
971
1008
 
972
1009
  return len(batch)
@@ -1,7 +1,8 @@
1
1
  # src/codegraphcontext/core/cgcignore.py
2
2
  from pathlib import Path
3
3
  from typing import Iterable, Optional, Tuple
4
- from pathspec import PathSpec
4
+ import re
5
+ from ..utils.debug_log import warning_logger
5
6
 
6
7
 
7
8
  def _resolve_explicit_path(ignore_root: Path, explicit_path: Optional[str]) -> Optional[Path]:
@@ -85,12 +86,134 @@ def read_cgcignore_patterns(path: Path, default_patterns: list[str]) -> list[str
85
86
  # User patterns first so explicit repo rules take precedence.
86
87
  return user_patterns + list(default_patterns)
87
88
 
89
+ class CGCIgnoreMatcher:
90
+ def __init__(self, patterns: list[str], root_dir: Path):
91
+ self.root_dir = root_dir
92
+ self.rules = self._compile_patterns(patterns)
93
+
94
+ def _translate_segment(self, seg: str) -> str:
95
+ """Translates a single gitwildmatch segment into regex, completely avoiding fnmatch."""
96
+ i, n = 0, len(seg)
97
+ res = ""
98
+ while i < n:
99
+ c = seg[i]
100
+ i += 1
101
+ if c == '*':
102
+ res += '[^/]*'
103
+ elif c == '?':
104
+ res += '[^/]'
105
+ elif c == '\\':
106
+ # Handle gitignore escape sequence (e.g. \! matches a literal !)
107
+ if i < n:
108
+ res += re.escape(seg[i])
109
+ i += 1
110
+ else:
111
+ res += re.escape('\\')
112
+ elif c == '[':
113
+ j = i
114
+ if j < n and seg[j] == '!':
115
+ j += 1
116
+ if j < n and seg[j] == ']':
117
+ j += 1
118
+ while j < n and seg[j] != ']':
119
+ j += 1
120
+ if j >= n:
121
+ res += '\\['
122
+ else:
123
+ stuff = seg[i:j].replace('\\', '\\\\')
124
+ i = j + 1
125
+ if stuff[0] == '!':
126
+ stuff = '^' + stuff[1:]
127
+ elif stuff[0] == '^':
128
+ stuff = '\\' + stuff
129
+ res += '[' + stuff + ']'
130
+ else:
131
+ res += re.escape(c)
132
+ return res
133
+
134
+ def _compile_patterns(self, patterns: list[str]) -> list[Tuple[bool, re.Pattern]]:
135
+ rules = []
136
+ for raw_pat in patterns:
137
+ pat = raw_pat.strip()
138
+ if not pat or pat.startswith('#'):
139
+ continue
140
+
141
+ is_negation = pat.startswith('!')
142
+ if is_negation:
143
+ pat = pat[1:]
144
+
145
+ is_dir_only = pat.endswith('/')
146
+ if is_dir_only:
147
+ pat = pat[:-1]
148
+
149
+ is_root_anchored = '/' in pat
150
+ if pat.startswith('/'):
151
+ pat = pat[1:]
152
+
153
+ segments = pat.split('**')
154
+ translated_segments = []
155
+ for seg in segments:
156
+ if seg:
157
+ translated_segments.append(self._translate_segment(seg))
158
+ else:
159
+ translated_segments.append('')
160
+
161
+ regex_str = '.*'.join(translated_segments)
162
+
163
+ if is_root_anchored:
164
+ regex_str = r'\A' + regex_str
165
+ else:
166
+ regex_str = r'(?:.*/)?' + regex_str
167
+
168
+ if is_dir_only:
169
+ # Must match a directory (so it must have trailing slash, or children)
170
+ regex_str = regex_str + r'(?:/.*)\Z'
171
+ else:
172
+ regex_str = regex_str + r'(?:/.*)?\Z'
173
+
174
+ try:
175
+ compiled = re.compile(regex_str, re.DOTALL)
176
+ rules.append((is_negation, compiled))
177
+ except re.error as e:
178
+ warning_logger(f"Failed to compile .cgcignore pattern '{raw_pat}': {e}")
179
+ continue
180
+
181
+ return rules
182
+
183
+ def match_file(self, file_path) -> bool:
184
+ """Returns True if the file should be ignored.
185
+
186
+ Note on directory-only patterns (e.g. `build/`):
187
+ Since we match on the path string, a directory-only pattern requires a
188
+ trailing slash in the input to be matched accurately. If the caller checks
189
+ a directory without appending a trailing slash (e.g. `match_file("build")`),
190
+ it will not match `build/` because we cannot distinguish it from a file named `build`.
191
+ Callers (like `safe_walk`) should append `/` to directory paths before calling this.
192
+ """
193
+ try:
194
+ if isinstance(file_path, Path) and file_path.is_absolute():
195
+ rel_path = str(file_path.relative_to(self.root_dir)).replace("\\", "/")
196
+ else:
197
+ rel_path = str(file_path).replace("\\", "/")
198
+ except ValueError:
199
+ # If not relative to root, just use absolute
200
+ rel_path = str(file_path).replace("\\", "/")
201
+
202
+ rel_path = rel_path.lstrip('/')
203
+
204
+ ignored = False
205
+ for is_neg, rule in self.rules:
206
+ if rule.search(rel_path):
207
+ ignored = not is_neg
208
+
209
+ return ignored
210
+
88
211
  def build_ignore_spec(
89
212
  ignore_root: Path,
90
213
  default_patterns: list[str],
91
214
  explicit_path: Optional[str] = None,
92
- ) -> Tuple[PathSpec, Optional[Path]]:
93
- """Build PathSpec using merged default + user .cgcignore patterns.
215
+ ) -> Tuple[CGCIgnoreMatcher, Optional[Path]]:
216
+ """Build CGCIgnoreMatcher using merged default + user .cgcignore patterns.
94
217
 
95
218
  Returns the compiled spec and the discovered/created .cgcignore path.
96
219
  """
@@ -116,4 +239,4 @@ def build_ignore_spec(
116
239
  )
117
240
 
118
241
  all_patterns = merged_user_patterns + list(default_patterns)
119
- return PathSpec.from_lines("gitwildmatch", all_patterns), local_cgcignore_path
242
+ return CGCIgnoreMatcher(all_patterns, ignore_root), local_cgcignore_path
@@ -34,7 +34,7 @@ class GraphBuilder:
34
34
  self.job_manager = job_manager
35
35
  self.loop = loop
36
36
  self.driver = self.db_manager.get_driver()
37
- self._writer = GraphWriter(self.driver)
37
+ self._writer = GraphWriter(self.driver, db_manager=self.db_manager)
38
38
  self.last_call_resolution_diagnostics: list[Dict[str, Any]] = []
39
39
  self.parsers = {
40
40
  ".py": "python",
@@ -65,9 +65,10 @@ def add_code_to_graph(graph_builder, job_manager, loop, list_repos_func, **args)
65
65
 
66
66
  if not path_obj.exists():
67
67
  return {
68
- "success": True,
68
+ "success": False,
69
69
  "status": "path_not_found",
70
- "message": f"Path '{path}' does not exist."
70
+ "error": f"Path '{path}' does not exist.",
71
+ "message": f"Path '{path}' does not exist.",
71
72
  }
72
73
 
73
74
  # Prevent re-indexing the same repository.
@@ -11,6 +11,7 @@ from typing import Any, Callable, Dict, List, Optional, Tuple
11
11
  from ....utils.debug_log import info_logger, warning_logger
12
12
  from ....utils.git_utils import get_repo_commit_hash
13
13
  from ..sanitize import sanitize_props
14
+ from ..schema_contract import NODE_LABELS
14
15
 
15
16
 
16
17
  def _is_binder_exception(e: Exception) -> bool:
@@ -22,8 +23,83 @@ def _is_binder_exception(e: Exception) -> bool:
22
23
  class GraphWriter:
23
24
  """Persists repository/file/symbol nodes and relationships via the Neo4j-like driver API."""
24
25
 
25
- def __init__(self, driver: Any):
26
+ def __init__(self, driver: Any, db_manager: Any = None):
26
27
  self.driver = driver
28
+ self._db_manager = db_manager
29
+ if db_manager is None:
30
+ warning_logger(
31
+ "[GraphWriter] db_manager not provided; "
32
+ "backend detection will default to 'neo4j'"
33
+ )
34
+
35
+ def _get_all_node_labels(self) -> list[str]:
36
+ """Discover all node labels in the database, backend-aware.
37
+
38
+ Neo4j / Nornic use ``CALL db.labels()``.
39
+ KuzuDB / LadybugDB use ``MATCH (n) RETURN DISTINCT label(n)``
40
+ (``SHOW TABLES`` is not supported in KuzuDB Python bindings ≤ 0.11).
41
+ FalkorDB uses ``CALL db.labels()`` without YIELD.
42
+ All backends fall back to :data:`schema_contract.NODE_LABELS`
43
+ plus supplementary labels on failure.
44
+ """
45
+ # Prefer db_manager.get_backend_type(); fall back to driver, then neo4j
46
+ backend = (
47
+ getattr(self._db_manager, "get_backend_type", None)
48
+ or getattr(self.driver, "get_backend_type", None)
49
+ or (lambda: "neo4j")
50
+ )()
51
+
52
+ if backend in ("kuzudb", "ladybugdb"):
53
+ # NOTE: Full node scan required because SHOW TABLES is unavailable
54
+ # in KuzuDB ≤ 0.11. Acceptable for delete_repository (low-frequency).
55
+ try:
56
+ with self.driver.session() as session:
57
+ result = session.run(
58
+ "MATCH (n) RETURN DISTINCT label(n) AS lbl"
59
+ )
60
+ labels = sorted(
61
+ {record[0] for record in result if record[0] is not None}
62
+ )
63
+ if labels:
64
+ return labels
65
+ except Exception as e:
66
+ info_logger(
67
+ f"[DELETE] label discovery failed for {backend} "
68
+ f"({e}), using fallback list"
69
+ )
70
+
71
+ elif backend in ("neo4j", "nornic"):
72
+ try:
73
+ with self.driver.session() as session:
74
+ label_records = session.run(
75
+ "CALL db.labels() YIELD label RETURN label"
76
+ )
77
+ return sorted({record["label"] for record in label_records})
78
+ except Exception as e:
79
+ info_logger(
80
+ f"[DELETE] CALL db.labels() failed for {backend} "
81
+ f"({e}), using fallback list"
82
+ )
83
+
84
+ elif backend in ("falkordb", "falkordb-remote"):
85
+ try:
86
+ with self.driver.session() as session:
87
+ label_records = session.run("CALL db.labels()")
88
+ return sorted({record["label"] for record in label_records})
89
+ except Exception as e:
90
+ info_logger(
91
+ f"[DELETE] CALL db.labels() failed for {backend} "
92
+ f"({e}), using fallback list"
93
+ )
94
+
95
+ # Fallback: canonical NODE_LABELS from schema_contract + supplementary
96
+ # labels that may exist in the graph from dynamic indexing paths.
97
+ return sorted(NODE_LABELS | {
98
+ "ExternalClass", "ExternalFunction",
99
+ "EnumValue", "Namespace", "TypeAlias", "Decorator",
100
+ "Method", "Endpoint", "OrmMapping", "Query",
101
+ "SpringDataRepository", "Mixin", "Extension", "Object",
102
+ })
27
103
 
28
104
  def add_repository_to_graph(self, repo_path: Path, is_dependency: bool = False) -> None:
29
105
  repo_name = repo_path.name
@@ -1364,17 +1440,16 @@ class GraphWriter:
1364
1440
  # list. Every time the indexer learned a new node type (Variable,
1365
1441
  # Parameter, Directory, ExternalClass, DbTable, ...) the hardcoded
1366
1442
  # tuple here had to be kept in lockstep, and every miss leaked
1367
- # orphan nodes on `delete_repository`. `CALL db.labels()` returns
1368
- # exactly the set of labels that have at least one node in the
1369
- # current database -- per-label DETACH DELETE with the same path
1370
- # prefix is then label-agnostic and self-maintaining.
1443
+ # orphan nodes on `delete_repository`.
1444
+ #
1445
+ # Neo4j: `CALL db.labels()` returns exactly the set of labels.
1446
+ # KuzuDB: `MATCH (n) RETURN DISTINCT label(n)` discovers labels dynamically.
1447
+ # Other backends: comprehensive fallback list.
1371
1448
  #
1372
1449
  # Labels with no node matching the path prefix are cheap: the
1373
1450
  # label-scoped scan returns 0 rows, the while-True loop exits
1374
1451
  # immediately, and we move on.
1375
- with self.driver.session() as session:
1376
- label_records = session.run("CALL db.labels() YIELD label RETURN label")
1377
- all_labels = sorted({record["label"] for record in label_records})
1452
+ all_labels = self._get_all_node_labels()
1378
1453
 
1379
1454
  for label in all_labels:
1380
1455
  while True:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraphcontext
3
- Version: 0.4.14
3
+ Version: 0.4.16
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
@@ -155,7 +155,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
155
155
  ---
156
156
 
157
157
  ## 📍 Quick Navigation
158
- * [🚀 Quick Start](#quick-start)
158
+ * [🚀 Quick Start](#-installation--quick-start)
159
159
  * [🌐 Supported Programming Languages](#supported-programming-languages)
160
160
  * [🛠️ CLI Toolkit](#for-cli-toolkit-mode)
161
161
  * [🤖 MCP Server](#-for-mcp-server-mode)
@@ -183,7 +183,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
183
183
  ---
184
184
 
185
185
  ## Project Details
186
- - **Version:** 0.4.14
186
+ - **Version:** 0.4.16
187
187
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
188
188
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
189
189
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -9,17 +9,17 @@ codegraphcontext/api/mcp_sse.py,sha256=VVQ_5s438SOJWSNwRinXgAmCE2Qhiz5rTGafwfp-K
9
9
  codegraphcontext/api/router.py,sha256=8iEhjERfGI5Udn801wMGpZmcmAuwbt5cMCwnK-Evg9Q,3229
10
10
  codegraphcontext/api/schemas.py,sha256=pGLuKtdn55pf8mS8wv8MwehbT_3-4OZuSYjI5LJxzOc,1034
11
11
  codegraphcontext/cli/__init__.py,sha256=2vUlnf7H09M9JbS2gS_LmMUBJWAWcGGHkkl4I2YrdSg,39
12
- codegraphcontext/cli/cli_helpers.py,sha256=_fksM3sBj9e96gQcHOaDmpmJG6444lWRaO0AM-6Wzu8,38773
13
- codegraphcontext/cli/config_manager.py,sha256=QX6IP5JqYFaItaLGAJjh2J2pQgcEOC58HVNK9iIyexU,44863
14
- codegraphcontext/cli/main.py,sha256=yOhEZDh4jmeo6avbjS5DqLHMEEkrZJlVCWV7R_pAw3g,116828
12
+ codegraphcontext/cli/cli_helpers.py,sha256=2TW5PWiaCo_htuZiqwCNYcjPKPKh9nDzMp82A3KDFOw,39748
13
+ codegraphcontext/cli/config_manager.py,sha256=3Bfco0sV07p7_WecvBru3Eim_VWdg5Ne9I-KCdsuUSE,45350
14
+ codegraphcontext/cli/main.py,sha256=y9fK-GVANefdCmvNS-TVTufB49I0FRwN6PZmbph_LZE,119777
15
15
  codegraphcontext/cli/registry_commands.py,sha256=8irzcdPV53PtERuytFfzm8KO5nEUPrgy9ZzyKL5oZ_0,17029
16
16
  codegraphcontext/cli/setup_macos.py,sha256=Xjlv_9jk9qv8Gh7stpH1pvlalzC0Fg176y7jc5G1zh0,3575
17
17
  codegraphcontext/cli/setup_wizard.py,sha256=_aZxOe3q4qIEQeaghDVsNPxMRcxJsvibrfqf39rSshI,47746
18
18
  codegraphcontext/cli/visualizer.py,sha256=md5HehQ9_8lBTejQqq2lxXtMRzDxCjjF9L9h2qu6KR0,1902
19
19
  codegraphcontext/core/__init__.py,sha256=mXMX6gBJ6DMad6lTvQvrpTxaSt1QfPMn3t_x1pZF4cg,10492
20
20
  codegraphcontext/core/bundle_registry.py,sha256=k3QZAGaLo2DV5p1xhqzgl_bf7faHCBfWT6ETYylSbKU,5711
21
- codegraphcontext/core/cgc_bundle.py,sha256=oLSMmLMJVd0JigFjJFXbzDRO4fKjuUD0Fl1_7OEBHHE,41052
22
- codegraphcontext/core/cgcignore.py,sha256=6q7y11V_bNEhMC1167HiUyr7yxDCNg2OMr0DQAqCzlE,4213
21
+ codegraphcontext/core/cgc_bundle.py,sha256=o5L1GPxZ23IxUEvzv6XeNFHQhsZIQr0aSFq-dM5lJU8,42854
22
+ codegraphcontext/core/cgcignore.py,sha256=O8dDWAhixIeTzLnL5I9dEe28oCzvBhUEQ0mAx3AH_ik,8753
23
23
  codegraphcontext/core/database.py,sha256=RWMdKKinoWewyTyTuIXX-fk7EHkba91LO18gZ12wwEg,14648
24
24
  codegraphcontext/core/database_falkordb.py,sha256=iN7uSvXFVp1clSjF2q92Omh4k6TlgAlS1-1QL9FF50o,25989
25
25
  codegraphcontext/core/database_falkordb_remote.py,sha256=aMiuJTB_-2rBUpbAmX8ElZiZrYZbOXK-On3ncgMCyhY,7118
@@ -32,7 +32,7 @@ codegraphcontext/core/watcher.py,sha256=EFjKYK3wUQG2pQter_A2xSe8yIrkZwfjZ9anITAj
32
32
  codegraphcontext/tools/__init__.py,sha256=iqQPEkDlGXO7rAaLNQrS_ZAbLSklBSK-OowpARq0mig,41
33
33
  codegraphcontext/tools/advanced_language_query_tool.py,sha256=sZ1_IjqyeIHW-KR4MjXQnEly8-B1hpsFctMdUCROODE,3914
34
34
  codegraphcontext/tools/code_finder.py,sha256=rSoyezvOedIeejN9INyb4kbniRctO25DR3tczvKAImo,70586
35
- codegraphcontext/tools/graph_builder.py,sha256=jb0j9q0JvbzXk5uCqvdvUP-iYmECiARJ3KX9fOvgrMo,54654
35
+ codegraphcontext/tools/graph_builder.py,sha256=Sn7zZG7zbwNqc9noH29cV1CXDrnykEsOGEMgCvD3v6g,54682
36
36
  codegraphcontext/tools/package_resolver.py,sha256=KtbdMReTezszjdsqYniL-Xb-QUsrAJWtf1NSiyIPkLI,18704
37
37
  codegraphcontext/tools/report_generator.py,sha256=K4AROEMZU--fX217JT6y7P7LfiqRnG8olwrj0vO1kKo,12499
38
38
  codegraphcontext/tools/scip_indexer.py,sha256=tHR362n_tVOhOykTKPnPpCdgk9iryu2DuxAfSNonvXM,36926
@@ -45,7 +45,7 @@ codegraphcontext/tools/datasources/cassandra_ingester.py,sha256=sgbskSkvE98qtOpr
45
45
  codegraphcontext/tools/datasources/mysql_ingester.py,sha256=uWstOv7mOEws1pmT8uAsEBkoOGM1FXOWt_2VCE-tZeg,3991
46
46
  codegraphcontext/tools/datasources/redis_ingester.py,sha256=mVUKYmr_v6g7wYaavmQscEHGi_CPZrxYLjfkldc6cWE,3788
47
47
  codegraphcontext/tools/handlers/analysis_handlers.py,sha256=d09od3Cs2O7_a7OGLul-_KHObZqCQM3vjXClrLHdfWk,12821
48
- codegraphcontext/tools/handlers/indexing_handlers.py,sha256=yyEPaQ4-RAtXxHXKRxWpRZM0lYrhbiyhYaYcHhHdm2A,6902
48
+ codegraphcontext/tools/handlers/indexing_handlers.py,sha256=w6RsHrda9Tkit-OVFxawAddVNKrarzowUoXEGDTViPg,6963
49
49
  codegraphcontext/tools/handlers/management_handlers.py,sha256=CbgvAAJlYc0yv5Jh0dDnqOYQoDKQORaDwzAw3fUZ1A8,14253
50
50
  codegraphcontext/tools/handlers/query_handlers.py,sha256=1GGbH86vX-qjk9TzDkvi-QLmsT3kT0y9E41m8h3hBcQ,4466
51
51
  codegraphcontext/tools/handlers/watcher_handlers.py,sha256=qsx1Qs_BXVEpKg8IG6Zxpseq_36z4WR3NjDYWGOc-vI,3479
@@ -61,7 +61,7 @@ codegraphcontext/tools/indexing/schema_contract.py,sha256=W8mU7HgvyVvNw3Mxrwc-tD
61
61
  codegraphcontext/tools/indexing/scip_pipeline.py,sha256=Uc3kSLNN4G1epLle5BvIQ-jtYJDAC4k1_j_cVFf_Dd4,8988
62
62
  codegraphcontext/tools/indexing/vector_resolver.py,sha256=RK2sj3n9_UVPVbfe9Isyn1GpfJTNrmPb830m9PF5yp4,5119
63
63
  codegraphcontext/tools/indexing/persistence/__init__.py,sha256=hFRlNgiYS7uN9X4e4xfP3c1BvcYSxpmq0k_uaDRn2Fg,121
64
- codegraphcontext/tools/indexing/persistence/writer.py,sha256=1KGK3UjEHygB4-AIfF2-O7dAt6G116YGvqUPo-GlROc,67887
64
+ codegraphcontext/tools/indexing/persistence/writer.py,sha256=vshr-cli3kSoEHiZgUeoweJ8FlAtL6VKvxX58tw43D4,71073
65
65
  codegraphcontext/tools/indexing/resolution/__init__.py,sha256=SWaJlN5kpWPjLoLUTLC4VEDaubpf0_tl5g7igGCbWJM,310
66
66
  codegraphcontext/tools/indexing/resolution/calls.py,sha256=R7o5ryWGCYL4h_DfnLaqdwpzSWYB6gTc8dbBWm-tAcM,107280
67
67
  codegraphcontext/tools/indexing/resolution/inheritance.py,sha256=BOYw_-NiO4oX5dS0CIX-ebg2ZhQhJ1NRC6Vk_tnAX-M,4118
@@ -154,9 +154,9 @@ codegraphcontext/viz/dist/wasm/tree-sitter-typescript.wasm,sha256=hRVATc7tOOHthq
154
154
  codegraphcontext/viz/dist/wasm/tree-sitter.wasm,sha256=CCeVuI_hXktkBD-DW01xYPv5XoAYVRIqzJUJI5te-RY,196763
155
155
  codegraphcontext/viz/dist/wasm/web-tree-sitter.js,sha256=DIaCNqRylrT_PBVw8g4ImeSnhP9uXNe_ycOlUiVGPko,153666
156
156
  codegraphcontext/viz/dist/wasm/web-tree-sitter.wasm,sha256=CCeVuI_hXktkBD-DW01xYPv5XoAYVRIqzJUJI5te-RY,196763
157
- codegraphcontext-0.4.14.dist-info/licenses/LICENSE,sha256=rh8M-bJpQYJnw2vtRVgt0t7piMZXh5QzaKeNEI0vqqA,1061
158
- codegraphcontext-0.4.14.dist-info/METADATA,sha256=MvD3fxmCeYy3c0isUirHNIhEGElnRr6cW4K937yv7aw,23904
159
- codegraphcontext-0.4.14.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
160
- codegraphcontext-0.4.14.dist-info/entry_points.txt,sha256=LCxWCWMshdvYGoHBPuQZ8C-e4CiNSHCLXofrNSGHkoE,103
161
- codegraphcontext-0.4.14.dist-info/top_level.txt,sha256=CBgc6LAPZIO5FS0nSYYkylDifHsZTIqw3Gf5UwDxeGI,17
162
- codegraphcontext-0.4.14.dist-info/RECORD,,
157
+ codegraphcontext-0.4.16.dist-info/licenses/LICENSE,sha256=rh8M-bJpQYJnw2vtRVgt0t7piMZXh5QzaKeNEI0vqqA,1061
158
+ codegraphcontext-0.4.16.dist-info/METADATA,sha256=6qMX2oZtd9IPsftIqBX98WdXyq8rhLa0kl26_GjRQSo,23919
159
+ codegraphcontext-0.4.16.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
160
+ codegraphcontext-0.4.16.dist-info/entry_points.txt,sha256=LCxWCWMshdvYGoHBPuQZ8C-e4CiNSHCLXofrNSGHkoE,103
161
+ codegraphcontext-0.4.16.dist-info/top_level.txt,sha256=CBgc6LAPZIO5FS0nSYYkylDifHsZTIqw3Gf5UwDxeGI,17
162
+ codegraphcontext-0.4.16.dist-info/RECORD,,