codegraphcontext 0.1.34__tar.gz → 0.1.35__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.
Files changed (83) hide show
  1. {codegraphcontext-0.1.34/src/codegraphcontext.egg-info → codegraphcontext-0.1.35}/PKG-INFO +2 -2
  2. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/README.md +1 -1
  3. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/pyproject.toml +1 -1
  4. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/cli/cli_helpers.py +12 -15
  5. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/cli/main.py +8 -3
  6. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/cli/registry_commands.py +135 -29
  7. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/core/cgc_bundle.py +23 -2
  8. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/core/database.py +5 -0
  9. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/core/database_falkordb.py +5 -0
  10. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35/src/codegraphcontext.egg-info}/PKG-INFO +2 -2
  11. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/LICENSE +0 -0
  12. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/MANIFEST.in +0 -0
  13. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/setup.cfg +0 -0
  14. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/__init__.py +0 -0
  15. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/__main__.py +0 -0
  16. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/cli/__init__.py +0 -0
  17. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/cli/config_manager.py +0 -0
  18. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/cli/setup_macos.py +0 -0
  19. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/cli/setup_wizard.py +0 -0
  20. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/cli/visualizer.py +0 -0
  21. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/core/__init__.py +0 -0
  22. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/core/falkor_worker.py +0 -0
  23. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/core/jobs.py +0 -0
  24. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/core/watcher.py +0 -0
  25. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/prompts.py +0 -0
  26. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/server.py +0 -0
  27. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tool_definitions.py +0 -0
  28. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/__init__.py +0 -0
  29. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/advanced_language_query_tool.py +0 -0
  30. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/code_finder.py +0 -0
  31. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/graph_builder.py +0 -0
  32. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/handlers/analysis_handlers.py +0 -0
  33. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/handlers/indexing_handlers.py +0 -0
  34. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/handlers/management_handlers.py +0 -0
  35. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/handlers/query_handlers.py +0 -0
  36. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/handlers/watcher_handlers.py +0 -0
  37. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/c.py +0 -0
  38. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/cpp.py +0 -0
  39. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/csharp.py +0 -0
  40. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/go.py +0 -0
  41. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/java.py +0 -0
  42. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/javascript.py +0 -0
  43. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/kotlin.py +0 -0
  44. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/php.py +0 -0
  45. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/python.py +0 -0
  46. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/ruby.py +0 -0
  47. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/rust.py +0 -0
  48. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/scala.py +0 -0
  49. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/swift.py +0 -0
  50. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/typescript.py +0 -0
  51. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/languages/typescriptjsx.py +0 -0
  52. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/package_resolver.py +0 -0
  53. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/c_toolkit.py +0 -0
  54. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/cpp_toolkit.py +0 -0
  55. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/csharp_toolkit.py +0 -0
  56. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/go_toolkit.py +0 -0
  57. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/java_toolkit.py +0 -0
  58. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/javascript_toolkit.py +0 -0
  59. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/python_toolkit.py +0 -0
  60. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/ruby_toolkit.py +0 -0
  61. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/rust_toolkit.py +0 -0
  62. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/scala_toolkit.py +0 -0
  63. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/swift_toolkit.py +0 -0
  64. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/query_tool_languages/typescript_toolkit.py +0 -0
  65. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/tools/system.py +0 -0
  66. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/utils/debug_log.py +0 -0
  67. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/utils/tree_sitter_manager.py +0 -0
  68. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext/utils/visualize_graph.py +0 -0
  69. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext.egg-info/SOURCES.txt +0 -0
  70. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext.egg-info/dependency_links.txt +0 -0
  71. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext.egg-info/entry_points.txt +0 -0
  72. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext.egg-info/requires.txt +0 -0
  73. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/src/codegraphcontext.egg-info/top_level.txt +0 -0
  74. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/tests/test_cpp_parser.py +0 -0
  75. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/tests/test_database_validation.py +0 -0
  76. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/tests/test_end_to_end.py +0 -0
  77. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/tests/test_graph_indexing.py +0 -0
  78. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/tests/test_graph_indexing_js.py +0 -0
  79. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/tests/test_kotlin_parser.py +0 -0
  80. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/tests/test_swift_parser.py +0 -0
  81. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/tests/test_tree_sitter_manager.py +0 -0
  82. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/tests/test_typescript_parser.py +0 -0
  83. {codegraphcontext-0.1.34 → codegraphcontext-0.1.35}/tests/test_visualization.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraphcontext
3
- Version: 0.1.34
3
+ Version: 0.1.35
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
@@ -91,7 +91,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
91
91
  ![Using the MCP server](https://github.com/CodeGraphContext/CodeGraphContext/blob/main/images/Usecase.gif)
92
92
 
93
93
  ## Project Details
94
- - **Version:** 0.1.34
94
+ - **Version:** 0.1.35
95
95
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
96
96
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
97
97
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -29,7 +29,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
29
29
  ![Using the MCP server](https://github.com/CodeGraphContext/CodeGraphContext/blob/main/images/Usecase.gif)
30
30
 
31
31
  ## Project Details
32
- - **Version:** 0.1.34
32
+ - **Version:** 0.1.35
33
33
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
34
34
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
35
35
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "codegraphcontext"
3
- version = "0.1.34"
3
+ version = "0.1.35"
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"
@@ -572,28 +572,25 @@ def stats_helper(path: str = None):
572
572
  console.print("[cyan]📊 Overall Database Statistics[/cyan]\n")
573
573
 
574
574
  with db_manager.get_driver().session() as session:
575
- # Get overall counts
575
+ # Get overall counts using separate queries to avoid empty results
576
+ # when some node types don't exist
576
577
  stats_query = """
577
578
  MATCH (r:Repository)
578
- WITH count(r) as repo_count
579
- MATCH (f:File)
580
- WITH repo_count, count(f) as file_count
581
- MATCH (func:Function)
582
- WITH repo_count, file_count, count(func) as function_count
583
- MATCH (cls:Class)
584
- WITH repo_count, file_count, function_count, count(cls) as class_count
585
- MATCH (m:Module)
579
+ OPTIONAL MATCH (f:File)
580
+ OPTIONAL MATCH (func:Function)
581
+ OPTIONAL MATCH (cls:Class)
582
+ OPTIONAL MATCH (m:Module)
586
583
  RETURN
587
- repo_count,
588
- file_count,
589
- function_count,
590
- class_count,
591
- count(m) as module_count
584
+ count(DISTINCT r) as repo_count,
585
+ count(DISTINCT f) as file_count,
586
+ count(DISTINCT func) as function_count,
587
+ count(DISTINCT cls) as class_count,
588
+ count(DISTINCT m) as module_count
592
589
  """
593
590
  result = session.run(stats_query)
594
591
  record = result.single()
595
592
 
596
- if record:
593
+ if record and record["repo_count"] > 0:
597
594
  table = Table(show_header=True, header_style="bold magenta")
598
595
  table.add_column("Metric", style="cyan")
599
596
  table.add_column("Count", style="green", justify="right")
@@ -44,9 +44,11 @@ from .cli_helpers import (
44
44
  list_watching_helper,
45
45
  )
46
46
 
47
- # Set the log level for the noisy neo4j and asyncio logger to WARNING to keep the output clean.
47
+ # Set the log level for the noisy neo4j, asyncio, and urllib3 loggers to WARNING to keep the output clean.
48
48
  logging.getLogger("neo4j").setLevel(logging.WARNING)
49
49
  logging.getLogger("asyncio").setLevel(logging.WARNING)
50
+ logging.getLogger("urllib3").setLevel(logging.WARNING)
51
+
50
52
 
51
53
  # Import visualization module
52
54
  from .visualizer import (
@@ -552,19 +554,22 @@ app.add_typer(registry_app, name="registry")
552
554
 
553
555
  @registry_app.command("list")
554
556
  def registry_list(
555
- verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed information including download URLs")
557
+ verbose: bool = typer.Option(False, "--verbose", "-v", help="Show detailed information including download URLs"),
558
+ unique: bool = typer.Option(False, "--unique", "-u", help="Show only one version per package (most recent)")
556
559
  ):
557
560
  """
558
561
  List all available bundles in the registry.
559
562
 
560
563
  Shows bundles from both weekly pre-indexed releases and on-demand generations.
564
+ By default, shows all versions. Use --unique to see only the most recent version per package.
561
565
 
562
566
  Examples:
563
567
  cgc registry list
564
568
  cgc registry list --verbose
569
+ cgc registry list --unique
565
570
  """
566
571
  from .registry_commands import list_bundles
567
- list_bundles(verbose=verbose)
572
+ list_bundles(verbose=verbose, unique=unique)
568
573
 
569
574
  @registry_app.command("search")
570
575
  def registry_search(
@@ -25,6 +25,7 @@ def fetch_available_bundles() -> List[Dict[str, Any]]:
25
25
  """
26
26
  Fetch all available bundles from GitHub Releases.
27
27
  Returns a list of bundle dictionaries with metadata.
28
+ Preserves all versions - no deduplication.
28
29
  """
29
30
  all_bundles = []
30
31
 
@@ -37,6 +38,10 @@ def fetch_available_bundles() -> List[Dict[str, Any]]:
37
38
  if manifest.get('bundles'):
38
39
  for bundle in manifest['bundles']:
39
40
  bundle['source'] = 'on-demand'
41
+ # Ensure bundle has a full_name field (with version info)
42
+ if 'bundle_name' in bundle:
43
+ # Extract full name without .cgc extension
44
+ bundle['full_name'] = bundle['bundle_name'].replace('.cgc', '')
40
45
  all_bundles.append(bundle)
41
46
  except Exception as e:
42
47
  console.print(f"[dim]Note: Could not fetch on-demand bundles: {e}[/dim]")
@@ -56,10 +61,14 @@ def fetch_available_bundles() -> List[Dict[str, Any]]:
56
61
 
57
62
  for asset in latest_weekly.get('assets', []):
58
63
  if asset['name'].endswith('.cgc'):
64
+ # Full bundle name without extension
65
+ full_name = asset['name'].replace('.cgc', '')
66
+
59
67
  # Parse bundle name
60
- name_parts = asset['name'].replace('.cgc', '').split('-')
68
+ name_parts = full_name.split('-')
61
69
  bundle = {
62
- 'name': name_parts[0],
70
+ 'name': name_parts[0], # Base package name
71
+ 'full_name': full_name, # Complete name with version
63
72
  'repo': f"{name_parts[0]}/{name_parts[0]}", # Simplified
64
73
  'bundle_name': asset['name'],
65
74
  'version': name_parts[1] if len(name_parts) > 1 else 'latest',
@@ -73,32 +82,60 @@ def fetch_available_bundles() -> List[Dict[str, Any]]:
73
82
  except Exception as e:
74
83
  console.print(f"[dim]Note: Could not fetch weekly bundles: {e}[/dim]")
75
84
 
76
- # Remove duplicates (prefer on-demand over weekly)
77
- unique_bundles = {}
85
+ # Normalize all bundles to have required fields
78
86
  for bundle in all_bundles:
79
- # Extract name from repo field (e.g., "pallets/flask" -> "flask")
80
- repo = bundle.get('repo', '')
81
- if '/' in repo:
82
- name = repo.split('/')[-1] # Get the last part after /
83
- else:
84
- name = bundle.get('name', repo.split('/')[-1] if '/' in repo else 'unknown')
87
+ # Ensure 'name' field exists (base package name)
88
+ if 'name' not in bundle:
89
+ repo = bundle.get('repo', '')
90
+ if '/' in repo:
91
+ bundle['name'] = repo.split('/')[-1]
92
+ else:
93
+ # Extract from full_name or bundle_name
94
+ full_name = bundle.get('full_name', bundle.get('bundle_name', 'unknown'))
95
+ bundle['name'] = full_name.split('-')[0]
85
96
 
86
- # Add name to bundle if not present
87
- if 'name' not in bundle or bundle['name'] == 'unknown':
88
- bundle['name'] = name
89
-
90
- if name not in unique_bundles or bundle.get('source') == 'on-demand':
91
- unique_bundles[name] = bundle
97
+ # Ensure 'full_name' exists
98
+ if 'full_name' not in bundle:
99
+ bundle['full_name'] = bundle.get('bundle_name', bundle.get('name', 'unknown')).replace('.cgc', '')
92
100
 
93
- return list(unique_bundles.values())
101
+ # NO DEDUPLICATION - Keep all versions
102
+ return all_bundles
94
103
 
95
104
  except Exception as e:
96
105
  console.print(f"[bold red]Error fetching bundles: {e}[/bold red]")
97
106
  return []
98
107
 
99
108
 
100
- def list_bundles(verbose: bool = False):
101
- """Display all available bundles in a table."""
109
+ def _get_base_package_name(bundle_name: str) -> str:
110
+ """
111
+ Extract base package name from full bundle name.
112
+
113
+ Examples:
114
+ 'python-bitcoin-utils-main-61d1969' -> 'python-bitcoin-utils'
115
+ 'flask-main-abc123' -> 'flask'
116
+ 'requests' -> 'requests'
117
+ """
118
+ # Remove .cgc extension if present
119
+ name = bundle_name.replace('.cgc', '')
120
+
121
+ # Split by hyphen and take the first part
122
+ # This assumes package names don't contain hyphens (may need refinement)
123
+ parts = name.split('-')
124
+
125
+ # For multi-word package names like 'python-bitcoin-utils',
126
+ # we need smarter logic. For now, take first part.
127
+ # TODO: Improve this with a known package list or better heuristics
128
+ return parts[0]
129
+
130
+
131
+ def list_bundles(verbose: bool = False, unique: bool = False):
132
+ """
133
+ Display all available bundles in a table.
134
+
135
+ Args:
136
+ verbose: Show additional details like download URLs
137
+ unique: Show only one version per package (most recent)
138
+ """
102
139
  console.print("[cyan]Fetching available bundles...[/cyan]")
103
140
 
104
141
  bundles = fetch_available_bundles()
@@ -108,9 +145,25 @@ def list_bundles(verbose: bool = False):
108
145
  console.print("[dim]The registry may be empty or unreachable.[/dim]")
109
146
  return
110
147
 
148
+ # If unique flag is set, keep only the most recent version per package
149
+ if unique:
150
+ unique_bundles = {}
151
+ for bundle in bundles:
152
+ base_name = bundle.get('name', 'unknown')
153
+ # Keep the one with the most recent timestamp
154
+ if base_name not in unique_bundles:
155
+ unique_bundles[base_name] = bundle
156
+ else:
157
+ # Compare timestamps (generated_at field)
158
+ current_time = bundle.get('generated_at', '')
159
+ existing_time = unique_bundles[base_name].get('generated_at', '')
160
+ if current_time > existing_time:
161
+ unique_bundles[base_name] = bundle
162
+ bundles = list(unique_bundles.values())
163
+
111
164
  # Create table
112
165
  table = Table(show_header=True, header_style="bold magenta", title="Available Bundles")
113
- table.add_column("Name", style="cyan", no_wrap=True)
166
+ table.add_column("Bundle Name", style="cyan", no_wrap=True)
114
167
  table.add_column("Repository", style="dim")
115
168
  table.add_column("Version", style="green")
116
169
  table.add_column("Size", justify="right")
@@ -119,11 +172,12 @@ def list_bundles(verbose: bool = False):
119
172
  if verbose:
120
173
  table.add_column("Download URL", style="blue", no_wrap=False)
121
174
 
122
- # Sort by name
123
- bundles.sort(key=lambda b: b.get('name', ''))
175
+ # Sort by full_name to group versions together
176
+ bundles.sort(key=lambda b: (b.get('name', ''), b.get('full_name', '')))
124
177
 
125
178
  for bundle in bundles:
126
- name = bundle.get('name', 'unknown')
179
+ # Use full_name for display (includes version info)
180
+ display_name = bundle.get('full_name', bundle.get('name', 'unknown'))
127
181
  repo = bundle.get('repo', 'unknown')
128
182
  version = bundle.get('version', bundle.get('tag', 'latest'))
129
183
  size = bundle.get('size', 'unknown')
@@ -131,12 +185,16 @@ def list_bundles(verbose: bool = False):
131
185
 
132
186
  if verbose:
133
187
  download_url = bundle.get('download_url', 'N/A')
134
- table.add_row(name, repo, version, size, source, download_url)
188
+ table.add_row(display_name, repo, version, size, source, download_url)
135
189
  else:
136
- table.add_row(name, repo, version, size, source)
190
+ table.add_row(display_name, repo, version, size, source)
137
191
 
138
192
  console.print(table)
139
193
  console.print(f"\n[dim]Total bundles: {len(bundles)}[/dim]")
194
+ if unique:
195
+ console.print("[dim]Showing only most recent version per package. Use without --unique to see all versions.[/dim]")
196
+ else:
197
+ console.print("[dim]Use --unique to show only one version per package[/dim]")
140
198
  console.print("[dim]Use 'cgc registry download <name>' to download a bundle[/dim]")
141
199
 
142
200
 
@@ -183,7 +241,12 @@ def search_bundles(query: str):
183
241
 
184
242
 
185
243
  def download_bundle(name: str, output_dir: Optional[str] = None, auto_load: bool = False):
186
- """Download a bundle from the registry."""
244
+ """
245
+ Download a bundle from the registry.
246
+
247
+ Supports both full names (e.g., 'python-bitcoin-utils-main-61d1969')
248
+ and base names (e.g., 'python-bitcoin-utils' - picks most recent version).
249
+ """
187
250
  console.print(f"[cyan]Looking for bundle '{name}'...[/cyan]")
188
251
 
189
252
  bundles = fetch_available_bundles()
@@ -192,16 +255,59 @@ def download_bundle(name: str, output_dir: Optional[str] = None, auto_load: bool
192
255
  console.print("[bold red]Could not fetch bundle registry.[/bold red]")
193
256
  raise typer.Exit(code=1)
194
257
 
195
- # Find the bundle
258
+ # Strategy 1: Try exact match on full_name (with version)
196
259
  bundle = None
197
260
  for b in bundles:
198
- if b.get('name', '').lower() == name.lower():
261
+ if b.get('full_name', '').lower() == name.lower():
199
262
  bundle = b
263
+ console.print(f"[dim]Found exact match: {b.get('full_name')}[/dim]")
200
264
  break
201
265
 
266
+ # Strategy 2: If no exact match, try matching base package name
267
+ # and pick the most recent version
202
268
  if not bundle:
269
+ matching_bundles = []
270
+ for b in bundles:
271
+ if b.get('name', '').lower() == name.lower():
272
+ matching_bundles.append(b)
273
+
274
+ if matching_bundles:
275
+ # Sort by timestamp and pick the most recent
276
+ matching_bundles.sort(key=lambda x: x.get('generated_at', ''), reverse=True)
277
+ bundle = matching_bundles[0]
278
+
279
+ console.print(f"[yellow]Multiple versions found for '{name}'. Using most recent:[/yellow]")
280
+ console.print(f"[cyan] → {bundle.get('full_name')}[/cyan]")
281
+
282
+ if len(matching_bundles) > 1:
283
+ console.print(f"\n[dim]Other available versions:[/dim]")
284
+ for b in matching_bundles[1:4]: # Show up to 3 alternatives
285
+ console.print(f"[dim] • {b.get('full_name')}[/dim]")
286
+ if len(matching_bundles) > 4:
287
+ console.print(f"[dim] ... and {len(matching_bundles) - 4} more[/dim]")
288
+ console.print()
289
+
290
+ # Strategy 3: No match found - show suggestions
291
+ if not bundle:
292
+ # Find bundles with similar base names
293
+ suggestions = []
294
+ name_lower = name.lower()
295
+ for b in bundles:
296
+ base_name = b.get('name', '').lower()
297
+ full_name = b.get('full_name', '').lower()
298
+
299
+ # Fuzzy matching: check if search term is in base or full name
300
+ if name_lower in base_name or name_lower in full_name:
301
+ suggestions.append(b.get('full_name', b.get('name', 'unknown')))
302
+
203
303
  console.print(f"[bold red]Bundle '{name}' not found in registry.[/bold red]")
204
- console.print("[dim]Use 'cgc registry list' to see available bundles[/dim]")
304
+
305
+ if suggestions:
306
+ console.print("\n[yellow]Did you mean one of these?[/yellow]")
307
+ for suggestion in suggestions[:5]: # Show top 5
308
+ console.print(f" • {suggestion}")
309
+
310
+ console.print("\n[dim]Use 'cgc registry list' to see all available bundles[/dim]")
205
311
  raise typer.Exit(code=1)
206
312
 
207
313
  # Get download URL
@@ -44,6 +44,21 @@ class CGCBundle:
44
44
  """
45
45
  self.db_manager = db_manager
46
46
 
47
+ def _get_id_function(self) -> str:
48
+ """
49
+ Get the appropriate ID function based on the database backend.
50
+
51
+ Returns:
52
+ str: 'elementId' for Neo4j, 'id' for FalkorDB
53
+ """
54
+ # Check if we're using Neo4j or FalkorDB
55
+ backend = self.db_manager.get_backend_type()
56
+ if backend == 'neo4j':
57
+ return 'elementId'
58
+ else: # FalkorDB or other backends
59
+ return 'id'
60
+
61
+
47
62
  def export_to_bundle(
48
63
  self,
49
64
  output_path: Path,
@@ -622,13 +637,16 @@ cgc import <bundle-file>.cgc
622
637
 
623
638
  def _import_node_batch(self, session, batch: List[Tuple], id_mapping: Dict) -> int:
624
639
  """Import a batch of nodes."""
640
+ # Detect database backend to use appropriate ID function
641
+ id_function = self._get_id_function()
642
+
625
643
  for labels, properties, old_id in batch:
626
644
  if not labels:
627
645
  continue
628
646
 
629
647
  # Create node with labels
630
648
  label_str = ':'.join(labels)
631
- query = f"CREATE (n:{label_str}) SET n = $props RETURN elementId(n) as new_id"
649
+ query = f"CREATE (n:{label_str}) SET n = $props RETURN {id_function}(n) as new_id"
632
650
 
633
651
  result = session.run(query, props=properties)
634
652
  record = result.single()
@@ -663,6 +681,8 @@ cgc import <bundle-file>.cgc
663
681
  def _import_edge_batch(self, session, batch: List[Dict]) -> int:
664
682
  """Import a batch of edges."""
665
683
  id_mapping = getattr(self, '_id_mapping', {})
684
+ # Detect database backend to use appropriate ID function
685
+ id_function = self._get_id_function()
666
686
 
667
687
  for edge in batch:
668
688
  old_from = edge.get('from')
@@ -681,7 +701,7 @@ cgc import <bundle-file>.cgc
681
701
  # Create relationship
682
702
  query = f"""
683
703
  MATCH (a), (b)
684
- WHERE elementId(a) = $from_id AND elementId(b) = $to_id
704
+ WHERE {id_function}(a) = $from_id AND {id_function}(b) = $to_id
685
705
  CREATE (a)-[r:{rel_type}]->(b)
686
706
  SET r = $props
687
707
  """
@@ -689,3 +709,4 @@ cgc import <bundle-file>.cgc
689
709
  session.run(query, from_id=new_from, to_id=new_to, props=properties)
690
710
 
691
711
  return len(batch)
712
+
@@ -121,6 +121,11 @@ class DatabaseManager:
121
121
  return True
122
122
  except Exception:
123
123
  return False
124
+
125
+ def get_backend_type(self) -> str:
126
+ """Returns the database backend type."""
127
+ return 'neo4j'
128
+
124
129
 
125
130
  @staticmethod
126
131
  def validate_config(uri: str, username: str, password: str) -> Tuple[bool, Optional[str]]:
@@ -225,6 +225,11 @@ class FalkorDBManager:
225
225
  return True
226
226
  except Exception:
227
227
  return False
228
+
229
+ def get_backend_type(self) -> str:
230
+ """Returns the database backend type."""
231
+ return 'falkordb'
232
+
228
233
 
229
234
  @staticmethod
230
235
  def validate_config(db_path: str = None) -> Tuple[bool, Optional[str]]:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codegraphcontext
3
- Version: 0.1.34
3
+ Version: 0.1.35
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
@@ -91,7 +91,7 @@ A powerful **MCP server** and **CLI toolkit** that indexes local code into a gra
91
91
  ![Using the MCP server](https://github.com/CodeGraphContext/CodeGraphContext/blob/main/images/Usecase.gif)
92
92
 
93
93
  ## Project Details
94
- - **Version:** 0.1.34
94
+ - **Version:** 0.1.35
95
95
  - **Authors:** Shashank Shekhar Singh <shashankshekharsingh1205@gmail.com>
96
96
  - **License:** MIT License (See [LICENSE](LICENSE) for details)
97
97
  - **Website:** [CodeGraphContext](http://codegraphcontext.vercel.app/)