agent-coderag 1.5.0__tar.gz → 1.5.1__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 (114) hide show
  1. {agent_coderag-1.5.0/agent_coderag.egg-info → agent_coderag-1.5.1}/PKG-INFO +1 -1
  2. {agent_coderag-1.5.0 → agent_coderag-1.5.1/agent_coderag.egg-info}/PKG-INFO +1 -1
  3. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/entry/args.py +4 -0
  4. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/parsers/tree_sitter.py +25 -13
  5. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/pyproject.toml +1 -1
  6. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_cli_startup.py +7 -0
  7. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_tree_sitter_parser.py +52 -0
  8. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/LICENSE +0 -0
  9. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/NOTICE +0 -0
  10. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/README.md +0 -0
  11. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/agent_coderag.egg-info/SOURCES.txt +0 -0
  12. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/agent_coderag.egg-info/dependency_links.txt +0 -0
  13. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/agent_coderag.egg-info/entry_points.txt +0 -0
  14. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/agent_coderag.egg-info/requires.txt +0 -0
  15. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/agent_coderag.egg-info/top_level.txt +0 -0
  16. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/__init__.py +0 -0
  17. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/api/__init__.py +0 -0
  18. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/api/client.py +0 -0
  19. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/api/models.py +0 -0
  20. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/core/__init__.py +0 -0
  21. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/core/constants.py +0 -0
  22. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/core/error_codes.py +0 -0
  23. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/core/exceptions.py +0 -0
  24. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/core/interfaces.py +0 -0
  25. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/core/models.py +0 -0
  26. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/core/utils.py +0 -0
  27. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/__init__.py +0 -0
  28. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/dependency.py +0 -0
  29. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/java_discovery.py +0 -0
  30. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/manager.py +0 -0
  31. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/providers/__init__.py +0 -0
  32. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/providers/base.py +0 -0
  33. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/providers/csharp.py +0 -0
  34. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/providers/go.py +0 -0
  35. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/providers/java.py +0 -0
  36. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/providers/javascript.py +0 -0
  37. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/providers/python.py +0 -0
  38. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/discovery/providers/rust.py +0 -0
  39. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/entry/__init__.py +0 -0
  40. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/entry/cli.py +0 -0
  41. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/intelligence/__init__.py +0 -0
  42. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/intelligence/distiller.py +0 -0
  43. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/intelligence/embedder.py +0 -0
  44. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/intelligence/factory.py +0 -0
  45. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/intelligence/openai_embedder.py +0 -0
  46. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/parsers/__init__.py +0 -0
  47. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/parsers/languages.py +0 -0
  48. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/parsers/multi_parser.py +0 -0
  49. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/paths.py +0 -0
  50. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/services/__init__.py +0 -0
  51. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/services/config.py +0 -0
  52. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/services/dependencies.py +0 -0
  53. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/services/discovery_api.py +0 -0
  54. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/services/factory.py +0 -0
  55. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/services/indexing.py +0 -0
  56. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/services/path_migration.py +0 -0
  57. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/services/search.py +0 -0
  58. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/services/setup.py +0 -0
  59. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/services/sync.py +0 -0
  60. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/storage/__init__.py +0 -0
  61. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/storage/db_connection.py +0 -0
  62. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/code_rag/storage/duckdb_impl.py +0 -0
  63. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/setup.cfg +0 -0
  64. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_api_client.py +0 -0
  65. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_api_lazy_db.py +0 -0
  66. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_api_models.py +0 -0
  67. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_api_rebuild_wipe.py +0 -0
  68. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_cli.py +0 -0
  69. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_cli_detailed.py +0 -0
  70. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_cli_embeddings.py +0 -0
  71. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_cli_json_parity.py +0 -0
  72. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_code_rag_simple.py +0 -0
  73. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_coderag_lifetime.py +0 -0
  74. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_csharp_discovery_detailed.py +0 -0
  75. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_db_connection.py +0 -0
  76. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_db_path.py +0 -0
  77. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_dependency_discovery.py +0 -0
  78. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_discovery_manager_detailed.py +0 -0
  79. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_discovery_providers_extra.py +0 -0
  80. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_discovery_python.py +0 -0
  81. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_distiller.py +0 -0
  82. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_distiller_config_embedding.py +0 -0
  83. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_distiller_extra.py +0 -0
  84. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_embedder.py +0 -0
  85. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_embedder_detailed.py +0 -0
  86. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_embedder_factory.py +0 -0
  87. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_embedder_interface.py +0 -0
  88. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_embedder_stubs.py +0 -0
  89. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_error_codes.py +0 -0
  90. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_factory_async.py +0 -0
  91. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_gitignore_root.py +0 -0
  92. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_indexing_detailed.py +0 -0
  93. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_indexing_embeddings.py +0 -0
  94. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_indexing_extra.py +0 -0
  95. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_interfaces.py +0 -0
  96. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_js_discovery_detailed.py +0 -0
  97. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_languages.py +0 -0
  98. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_local_onnx_embedder.py +0 -0
  99. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_migration_cli_e2e.py +0 -0
  100. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_migration_coderag.py +0 -0
  101. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_models.py +0 -0
  102. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_multi_parser.py +0 -0
  103. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_openai_embedder.py +0 -0
  104. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_path_migration.py +0 -0
  105. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_readme_library_usage.py +0 -0
  106. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_readme_lifetime_storage.py +0 -0
  107. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_readme_offline_embeddings.py +0 -0
  108. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_relative_sync_paths.py +0 -0
  109. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_rust_discovery_detailed.py +0 -0
  110. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_search_relative_paths.py +0 -0
  111. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_storage_detailed.py +0 -0
  112. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_storage_embeddings.py +0 -0
  113. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_sync_worker_errors.py +0 -0
  114. {agent_coderag-1.5.0 → agent_coderag-1.5.1}/tests/test_utils_detailed.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-coderag
3
- Version: 1.5.0
3
+ Version: 1.5.1
4
4
  Summary: Lightweight semantic code search and distillation utility for AI coding agents. It solves the API knowledge gap via real-time local signature extraction and intent analysis without PyTorch. Optimized for token efficiency, it compresses codebase context into compact semantic summaries stored in a local DuckDB vector similarity index.
5
5
  Author-email: Igor Boloban <naranor@gmail.com>
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agent-coderag
3
- Version: 1.5.0
3
+ Version: 1.5.1
4
4
  Summary: Lightweight semantic code search and distillation utility for AI coding agents. It solves the API knowledge gap via real-time local signature extraction and intent analysis without PyTorch. Optimized for token efficiency, it compresses codebase context into compact semantic summaries stored in a local DuckDB vector similarity index.
5
5
  Author-email: Igor Boloban <naranor@gmail.com>
6
6
  License: MIT
@@ -118,3 +118,7 @@ def main() -> None:
118
118
  except Exception as exc:
119
119
  logging.getLogger(__name__).error("Unexpected error: %s", exc)
120
120
  sys.exit(1)
121
+
122
+
123
+ if __name__ == "__main__":
124
+ main()
@@ -74,6 +74,7 @@ class TreeSitterParser(IParser):
74
74
  "file_path": identity,
75
75
  "units": units,
76
76
  "scope": None,
77
+ "name_counts": {},
77
78
  }
78
79
  self._recursive_distill(tree.root_node, ctx)
79
80
  return units
@@ -87,21 +88,35 @@ class TreeSitterParser(IParser):
87
88
 
88
89
  def _recursive_distill(self, node: Node, ctx: Dict[str, Any]) -> None:
89
90
  config = ctx["config"]
90
- current_scope = ctx["scope"]
91
+ child_scope = ctx["scope"]
92
+ child_counts = ctx["name_counts"]
91
93
 
92
94
  if node.type in config.canonical_map:
93
- self._process_node(node, ctx)
94
- if config.canonical_map.get(node.type) == "CLASS":
95
- node_name = self._resolve_name(node)
96
- scope = ctx["scope"]
97
- current_scope = f"{scope}.{node_name}" if scope else node_name
98
-
99
- # Recurse into children with updated scope
100
- child_ctx = {**ctx, "scope": current_scope}
95
+ qname = self._qualified_name(node, ctx)
96
+ self._process_node(node, ctx, qname)
97
+ if config.canonical_map.get(node.type) in ("CLASS", "FUNCTION", "METHOD"):
98
+ child_scope = qname
99
+ child_counts = {}
100
+
101
+ child_ctx = {**ctx, "scope": child_scope, "name_counts": child_counts}
101
102
  for child in node.children:
102
103
  self._recursive_distill(child, child_ctx)
103
104
 
104
- def _process_node(self, node: Node, ctx: Dict[str, Any]) -> None:
105
+ def _qualified_name(self, node: Node, ctx: Dict[str, Any]) -> str:
106
+ """Qualified id segment. Enclosing functions are part of the scope.
107
+
108
+ A repeated name in the same scope gets ``#2``, ``#3``, … so two
109
+ different bodies cannot share one primary key.
110
+ """
111
+ node_name = self._resolve_name(node)
112
+ counts: Dict[str, int] = ctx["name_counts"]
113
+ counts[node_name] = counts.get(node_name, 0) + 1
114
+ seen = counts[node_name]
115
+ label = node_name if seen == 1 else f"{node_name}#{seen}"
116
+ scope = ctx["scope"]
117
+ return f"{scope}.{label}" if scope else label
118
+
119
+ def _process_node(self, node: Node, ctx: Dict[str, Any], qname: str) -> None:
105
120
  """Processes a single node and adds it to the units list."""
106
121
  node_name = self._resolve_name(node)
107
122
  docstring = self._extract_docstring(node)
@@ -113,9 +128,6 @@ class TreeSitterParser(IParser):
113
128
 
114
129
  kind = self._determine_kind(node, ctx["config"])
115
130
 
116
- # Stable ID based on qualified name
117
- scope = ctx["scope"]
118
- qname = f"{scope}.{node_name}" if scope else node_name
119
131
  unit_id = f"{ctx['file_path']}:{qname}"
120
132
 
121
133
  unit = KnowledgeUnit(
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "agent-coderag"
7
- version = "1.5.0"
7
+ version = "1.5.1"
8
8
  description = "Lightweight semantic code search and distillation utility for AI coding agents. It solves the API knowledge gap via real-time local signature extraction and intent analysis without PyTorch. Optimized for token efficiency, it compresses codebase context into compact semantic summaries stored in a local DuckDB vector similarity index."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -1,3 +1,4 @@
1
+ import runpy
1
2
  import subprocess
2
3
  import sys
3
4
  from types import SimpleNamespace
@@ -33,6 +34,12 @@ assert "onnxruntime" not in sys.modules
33
34
  assert result.returncode == 0, result.stderr
34
35
 
35
36
 
37
+ def test_dunder_main_invokes_main(capsys):
38
+ with patch("sys.argv", ["agent-coderag"]):
39
+ runpy.run_path(cli_args.__file__, run_name="__main__")
40
+ assert "CodeRAG" in capsys.readouterr().out
41
+
42
+
36
43
  def test_main_help_and_verbose_do_not_dispatch(capsys):
37
44
  with patch("sys.argv", ["agent-coderag"]):
38
45
  cli_args.main()
@@ -114,6 +114,58 @@ const arrow = (x) => {
114
114
  os.unlink(temp_path)
115
115
 
116
116
 
117
+ @pytest.mark.asyncio
118
+ async def test_nested_functions_keep_distinct_ids():
119
+ parser = TreeSitterParser()
120
+ content = """
121
+ def test_one():
122
+ def helper():
123
+ return 1
124
+
125
+ def test_two():
126
+ def helper():
127
+ return 2
128
+
129
+ def same_scope():
130
+ def helper():
131
+ return 3
132
+
133
+ def helper():
134
+ return 4
135
+ """
136
+ with tempfile.NamedTemporaryFile(suffix=".py", delete=False) as f:
137
+ f.write(content.encode("utf-8"))
138
+ temp_path = f.name
139
+
140
+ try:
141
+ units = await parser.distill_file(temp_path)
142
+ ids = [unit.id for unit in units]
143
+ assert f"{temp_path}:test_one.helper" in ids
144
+ assert f"{temp_path}:test_two.helper" in ids
145
+ assert f"{temp_path}:same_scope.helper" in ids
146
+ assert f"{temp_path}:same_scope.helper#2" in ids
147
+ assert len(ids) == len(set(ids))
148
+ finally:
149
+ os.unlink(temp_path)
150
+
151
+
152
+ @pytest.mark.asyncio
153
+ async def test_export_does_not_wrap_inner_function_scope():
154
+ parser = TreeSitterParser()
155
+ content = "export function exportedFn() { return 1; }\n"
156
+ with tempfile.NamedTemporaryFile(suffix=".js", delete=False) as f:
157
+ f.write(content.encode("utf-8"))
158
+ temp_path = f.name
159
+
160
+ try:
161
+ units = await parser.distill_file(temp_path)
162
+ ids = {unit.id for unit in units}
163
+ assert f"{temp_path}:anonymous" in ids
164
+ assert f"{temp_path}:exportedFn" in ids
165
+ finally:
166
+ os.unlink(temp_path)
167
+
168
+
117
169
  @pytest.mark.asyncio
118
170
  async def test_missing_grammar():
119
171
  parser = TreeSitterParser()
File without changes
File without changes
File without changes
File without changes