agent-coderag 1.3.1__tar.gz → 1.3.3__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.
- {agent_coderag-1.3.1/agent_coderag.egg-info → agent_coderag-1.3.3}/PKG-INFO +26 -3
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/README.md +23 -1
- {agent_coderag-1.3.1 → agent_coderag-1.3.3/agent_coderag.egg-info}/PKG-INFO +26 -3
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/agent_coderag.egg-info/SOURCES.txt +14 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/agent_coderag.egg-info/requires.txt +2 -1
- agent_coderag-1.3.3/code_rag/__init__.py +16 -0
- agent_coderag-1.3.3/code_rag/api/__init__.py +6 -0
- agent_coderag-1.3.3/code_rag/api/client.py +87 -0
- agent_coderag-1.3.3/code_rag/api/models.py +20 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/core/manager.py +14 -1
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/entry/cli.py +90 -106
- agent_coderag-1.3.3/code_rag/services/config.py +25 -0
- agent_coderag-1.3.3/code_rag/services/discovery_api.py +8 -0
- agent_coderag-1.3.3/code_rag/services/factory.py +28 -0
- agent_coderag-1.3.3/code_rag/services/search.py +6 -0
- agent_coderag-1.3.3/code_rag/services/setup.py +72 -0
- agent_coderag-1.3.3/code_rag/services/sync.py +101 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/pyproject.toml +3 -2
- agent_coderag-1.3.3/tests/test_api_client.py +186 -0
- agent_coderag-1.3.3/tests/test_api_models.py +25 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_cli.py +26 -0
- agent_coderag-1.3.3/tests/test_cli_json_parity.py +100 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_manager_detailed.py +30 -1
- agent_coderag-1.3.3/tests/test_readme_library_usage.py +8 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/LICENSE +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/NOTICE +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/agent_coderag.egg-info/dependency_links.txt +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/agent_coderag.egg-info/entry_points.txt +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/agent_coderag.egg-info/top_level.txt +0 -0
- {agent_coderag-1.3.1/code_rag → agent_coderag-1.3.3/code_rag/core}/__init__.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/core/constants.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/core/exceptions.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/core/interfaces.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/core/models.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/core/utils.py +0 -0
- {agent_coderag-1.3.1/code_rag/core → agent_coderag-1.3.3/code_rag/discovery}/__init__.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/discovery/dependency.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/discovery/java_discovery.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/discovery/manager.py +0 -0
- {agent_coderag-1.3.1/code_rag/discovery → agent_coderag-1.3.3/code_rag/discovery/providers}/__init__.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/discovery/providers/base.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/discovery/providers/csharp.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/discovery/providers/go.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/discovery/providers/java.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/discovery/providers/javascript.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/discovery/providers/python.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/discovery/providers/rust.py +0 -0
- {agent_coderag-1.3.1/code_rag/discovery/providers → agent_coderag-1.3.3/code_rag/entry}/__init__.py +0 -0
- {agent_coderag-1.3.1/code_rag/entry → agent_coderag-1.3.3/code_rag/intelligence}/__init__.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/intelligence/distiller.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/intelligence/embedder.py +0 -0
- {agent_coderag-1.3.1/code_rag/intelligence → agent_coderag-1.3.3/code_rag/parsers}/__init__.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/parsers/languages.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/parsers/multi_parser.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/parsers/tree_sitter.py +0 -0
- {agent_coderag-1.3.1/code_rag/parsers → agent_coderag-1.3.3/code_rag/services}/__init__.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/storage/__init__.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/code_rag/storage/duckdb_impl.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/setup.cfg +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_cli_detailed.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_code_rag_simple.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_csharp_discovery_detailed.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_dependency_discovery.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_discovery_manager_detailed.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_discovery_providers_extra.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_discovery_python.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_distiller.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_distiller_extra.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_embedder.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_embedder_detailed.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_interfaces.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_js_discovery_detailed.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_languages.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_manager_extra.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_models.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_multi_parser.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_rust_discovery_detailed.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_storage_detailed.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/tests/test_tree_sitter_parser.py +0 -0
- {agent_coderag-1.3.1 → agent_coderag-1.3.3}/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.3.
|
|
3
|
+
Version: 1.3.3
|
|
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
|
|
@@ -24,11 +24,12 @@ License-File: LICENSE
|
|
|
24
24
|
License-File: NOTICE
|
|
25
25
|
Requires-Dist: duckdb
|
|
26
26
|
Requires-Dist: numpy
|
|
27
|
-
Requires-Dist: litellm
|
|
27
|
+
Requires-Dist: litellm==1.96.2
|
|
28
28
|
Requires-Dist: onnxruntime
|
|
29
29
|
Requires-Dist: tokenizers
|
|
30
30
|
Requires-Dist: pydantic
|
|
31
31
|
Requires-Dist: httpx
|
|
32
|
+
Requires-Dist: requests
|
|
32
33
|
Requires-Dist: aiofiles
|
|
33
34
|
Requires-Dist: pathspec
|
|
34
35
|
Requires-Dist: tree-sitter
|
|
@@ -123,10 +124,17 @@ If you don't configure an LLM provider, agent-coderag works in **100% Offline Mo
|
|
|
123
124
|
# Index your entire project (respects .gitignore automatically)
|
|
124
125
|
agent-coderag sync --all
|
|
125
126
|
|
|
127
|
+
# Trusted Maven/Gradle projects only: allow dependency resolution
|
|
128
|
+
agent-coderag sync --all --allow-build-execution
|
|
129
|
+
|
|
126
130
|
# Perform a semantic search
|
|
127
131
|
agent-coderag search "how does the authentication middleware work?"
|
|
128
132
|
```
|
|
129
133
|
|
|
134
|
+
Dependency build execution is disabled by default. Maven and Gradle build files
|
|
135
|
+
can execute repository-controlled code, so use `--allow-build-execution` only
|
|
136
|
+
after you have reviewed and trust the project.
|
|
137
|
+
|
|
130
138
|
### API Discovery
|
|
131
139
|
Verify external library signatures without leaving the CLI:
|
|
132
140
|
```bash
|
|
@@ -141,12 +149,27 @@ agent-coderag api fmt
|
|
|
141
149
|
|
|
142
150
|
---
|
|
143
151
|
|
|
152
|
+
## Library Usage
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from code_rag import CodeRAG
|
|
156
|
+
|
|
157
|
+
async def main():
|
|
158
|
+
async with CodeRAG(db="code_rag.db") as rag:
|
|
159
|
+
await rag.setup()
|
|
160
|
+
await rag.sync(index_all=True)
|
|
161
|
+
hits = await rag.search("authentication middleware", limit=5)
|
|
162
|
+
report = await rag.api("pydantic", lang="python")
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
144
167
|
## Supported Ecosystems (Discovery)
|
|
145
168
|
|
|
146
169
|
| Language | Method | Discovery Source |
|
|
147
170
|
| :--- | :--- | :--- |
|
|
148
171
|
| **Python** | 3-Stage Probe | `.pyi` stubs, static source, or runtime `inspect` |
|
|
149
|
-
| **Java** | Bytecode Reflection | JARs resolved via Maven
|
|
172
|
+
| **Java** | Bytecode Reflection | JARs resolved via Maven or Gradle with explicit `--allow-build-execution` opt-in |
|
|
150
173
|
| **Go** | Standard Tooling | Native `go doc -all` integration |
|
|
151
174
|
| **TypeScript/JS** | Declaration Maps | `.d.ts` files from `node_modules` or `@types` |
|
|
152
175
|
| **Rust** | Registry Analysis | Source code from Cargo registry via `cargo metadata` |
|
|
@@ -78,10 +78,17 @@ If you don't configure an LLM provider, agent-coderag works in **100% Offline Mo
|
|
|
78
78
|
# Index your entire project (respects .gitignore automatically)
|
|
79
79
|
agent-coderag sync --all
|
|
80
80
|
|
|
81
|
+
# Trusted Maven/Gradle projects only: allow dependency resolution
|
|
82
|
+
agent-coderag sync --all --allow-build-execution
|
|
83
|
+
|
|
81
84
|
# Perform a semantic search
|
|
82
85
|
agent-coderag search "how does the authentication middleware work?"
|
|
83
86
|
```
|
|
84
87
|
|
|
88
|
+
Dependency build execution is disabled by default. Maven and Gradle build files
|
|
89
|
+
can execute repository-controlled code, so use `--allow-build-execution` only
|
|
90
|
+
after you have reviewed and trust the project.
|
|
91
|
+
|
|
85
92
|
### API Discovery
|
|
86
93
|
Verify external library signatures without leaving the CLI:
|
|
87
94
|
```bash
|
|
@@ -96,12 +103,27 @@ agent-coderag api fmt
|
|
|
96
103
|
|
|
97
104
|
---
|
|
98
105
|
|
|
106
|
+
## Library Usage
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
from code_rag import CodeRAG
|
|
110
|
+
|
|
111
|
+
async def main():
|
|
112
|
+
async with CodeRAG(db="code_rag.db") as rag:
|
|
113
|
+
await rag.setup()
|
|
114
|
+
await rag.sync(index_all=True)
|
|
115
|
+
hits = await rag.search("authentication middleware", limit=5)
|
|
116
|
+
report = await rag.api("pydantic", lang="python")
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
99
121
|
## Supported Ecosystems (Discovery)
|
|
100
122
|
|
|
101
123
|
| Language | Method | Discovery Source |
|
|
102
124
|
| :--- | :--- | :--- |
|
|
103
125
|
| **Python** | 3-Stage Probe | `.pyi` stubs, static source, or runtime `inspect` |
|
|
104
|
-
| **Java** | Bytecode Reflection | JARs resolved via Maven
|
|
126
|
+
| **Java** | Bytecode Reflection | JARs resolved via Maven or Gradle with explicit `--allow-build-execution` opt-in |
|
|
105
127
|
| **Go** | Standard Tooling | Native `go doc -all` integration |
|
|
106
128
|
| **TypeScript/JS** | Declaration Maps | `.d.ts` files from `node_modules` or `@types` |
|
|
107
129
|
| **Rust** | Registry Analysis | Source code from Cargo registry via `cargo metadata` |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-coderag
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.3
|
|
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
|
|
@@ -24,11 +24,12 @@ License-File: LICENSE
|
|
|
24
24
|
License-File: NOTICE
|
|
25
25
|
Requires-Dist: duckdb
|
|
26
26
|
Requires-Dist: numpy
|
|
27
|
-
Requires-Dist: litellm
|
|
27
|
+
Requires-Dist: litellm==1.96.2
|
|
28
28
|
Requires-Dist: onnxruntime
|
|
29
29
|
Requires-Dist: tokenizers
|
|
30
30
|
Requires-Dist: pydantic
|
|
31
31
|
Requires-Dist: httpx
|
|
32
|
+
Requires-Dist: requests
|
|
32
33
|
Requires-Dist: aiofiles
|
|
33
34
|
Requires-Dist: pathspec
|
|
34
35
|
Requires-Dist: tree-sitter
|
|
@@ -123,10 +124,17 @@ If you don't configure an LLM provider, agent-coderag works in **100% Offline Mo
|
|
|
123
124
|
# Index your entire project (respects .gitignore automatically)
|
|
124
125
|
agent-coderag sync --all
|
|
125
126
|
|
|
127
|
+
# Trusted Maven/Gradle projects only: allow dependency resolution
|
|
128
|
+
agent-coderag sync --all --allow-build-execution
|
|
129
|
+
|
|
126
130
|
# Perform a semantic search
|
|
127
131
|
agent-coderag search "how does the authentication middleware work?"
|
|
128
132
|
```
|
|
129
133
|
|
|
134
|
+
Dependency build execution is disabled by default. Maven and Gradle build files
|
|
135
|
+
can execute repository-controlled code, so use `--allow-build-execution` only
|
|
136
|
+
after you have reviewed and trust the project.
|
|
137
|
+
|
|
130
138
|
### API Discovery
|
|
131
139
|
Verify external library signatures without leaving the CLI:
|
|
132
140
|
```bash
|
|
@@ -141,12 +149,27 @@ agent-coderag api fmt
|
|
|
141
149
|
|
|
142
150
|
---
|
|
143
151
|
|
|
152
|
+
## Library Usage
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from code_rag import CodeRAG
|
|
156
|
+
|
|
157
|
+
async def main():
|
|
158
|
+
async with CodeRAG(db="code_rag.db") as rag:
|
|
159
|
+
await rag.setup()
|
|
160
|
+
await rag.sync(index_all=True)
|
|
161
|
+
hits = await rag.search("authentication middleware", limit=5)
|
|
162
|
+
report = await rag.api("pydantic", lang="python")
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
144
167
|
## Supported Ecosystems (Discovery)
|
|
145
168
|
|
|
146
169
|
| Language | Method | Discovery Source |
|
|
147
170
|
| :--- | :--- | :--- |
|
|
148
171
|
| **Python** | 3-Stage Probe | `.pyi` stubs, static source, or runtime `inspect` |
|
|
149
|
-
| **Java** | Bytecode Reflection | JARs resolved via Maven
|
|
172
|
+
| **Java** | Bytecode Reflection | JARs resolved via Maven or Gradle with explicit `--allow-build-execution` opt-in |
|
|
150
173
|
| **Go** | Standard Tooling | Native `go doc -all` integration |
|
|
151
174
|
| **TypeScript/JS** | Declaration Maps | `.d.ts` files from `node_modules` or `@types` |
|
|
152
175
|
| **Rust** | Registry Analysis | Source code from Cargo registry via `cargo metadata` |
|
|
@@ -9,6 +9,9 @@ agent_coderag.egg-info/entry_points.txt
|
|
|
9
9
|
agent_coderag.egg-info/requires.txt
|
|
10
10
|
agent_coderag.egg-info/top_level.txt
|
|
11
11
|
code_rag/__init__.py
|
|
12
|
+
code_rag/api/__init__.py
|
|
13
|
+
code_rag/api/client.py
|
|
14
|
+
code_rag/api/models.py
|
|
12
15
|
code_rag/core/__init__.py
|
|
13
16
|
code_rag/core/constants.py
|
|
14
17
|
code_rag/core/exceptions.py
|
|
@@ -37,10 +40,20 @@ code_rag/parsers/__init__.py
|
|
|
37
40
|
code_rag/parsers/languages.py
|
|
38
41
|
code_rag/parsers/multi_parser.py
|
|
39
42
|
code_rag/parsers/tree_sitter.py
|
|
43
|
+
code_rag/services/__init__.py
|
|
44
|
+
code_rag/services/config.py
|
|
45
|
+
code_rag/services/discovery_api.py
|
|
46
|
+
code_rag/services/factory.py
|
|
47
|
+
code_rag/services/search.py
|
|
48
|
+
code_rag/services/setup.py
|
|
49
|
+
code_rag/services/sync.py
|
|
40
50
|
code_rag/storage/__init__.py
|
|
41
51
|
code_rag/storage/duckdb_impl.py
|
|
52
|
+
tests/test_api_client.py
|
|
53
|
+
tests/test_api_models.py
|
|
42
54
|
tests/test_cli.py
|
|
43
55
|
tests/test_cli_detailed.py
|
|
56
|
+
tests/test_cli_json_parity.py
|
|
44
57
|
tests/test_code_rag_simple.py
|
|
45
58
|
tests/test_csharp_discovery_detailed.py
|
|
46
59
|
tests/test_dependency_discovery.py
|
|
@@ -58,6 +71,7 @@ tests/test_manager_detailed.py
|
|
|
58
71
|
tests/test_manager_extra.py
|
|
59
72
|
tests/test_models.py
|
|
60
73
|
tests/test_multi_parser.py
|
|
74
|
+
tests/test_readme_library_usage.py
|
|
61
75
|
tests/test_rust_discovery_detailed.py
|
|
62
76
|
tests/test_storage_detailed.py
|
|
63
77
|
tests/test_tree_sitter_parser.py
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from code_rag.api.client import CodeRAG
|
|
2
|
+
from code_rag.api.models import SyncResult, ApiReport, SetupResult
|
|
3
|
+
from code_rag.core.models import KnowledgeUnit, UnitKind
|
|
4
|
+
from code_rag.intelligence.distiller import DistillerConfig
|
|
5
|
+
from code_rag.core.exceptions import CodeRAGError
|
|
6
|
+
|
|
7
|
+
__all__ = [
|
|
8
|
+
"CodeRAG",
|
|
9
|
+
"SyncResult",
|
|
10
|
+
"ApiReport",
|
|
11
|
+
"SetupResult",
|
|
12
|
+
"KnowledgeUnit",
|
|
13
|
+
"UnitKind",
|
|
14
|
+
"DistillerConfig",
|
|
15
|
+
"CodeRAGError",
|
|
16
|
+
]
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"""Public API package for CodeRAG.
|
|
2
|
+
|
|
3
|
+
`CodeRAG` lives in `code_rag.api.client` and is re-exported from top-level
|
|
4
|
+
`code_rag`. Import models from `code_rag.api.models` directly; this package
|
|
5
|
+
init stays empty to avoid circular imports with `code_rag.services.*`.
|
|
6
|
+
"""
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
from pathlib import Path
|
|
2
|
+
from typing import Optional, Union
|
|
3
|
+
|
|
4
|
+
from code_rag.api.models import ApiReport, SetupResult, SyncResult
|
|
5
|
+
from code_rag.core.models import KnowledgeUnit
|
|
6
|
+
from code_rag.intelligence.distiller import DistillerConfig
|
|
7
|
+
from code_rag.services.config import load_or_update_config
|
|
8
|
+
from code_rag.services.discovery_api import run_api
|
|
9
|
+
from code_rag.services.factory import create_manager
|
|
10
|
+
from code_rag.services.search import run_search
|
|
11
|
+
from code_rag.services.setup import run_setup
|
|
12
|
+
from code_rag.services.sync import run_rebuild, run_sync
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class CodeRAG:
|
|
16
|
+
"""Public async facade over CodeRAG services and the storage/search manager."""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
db: str = "code_rag.db",
|
|
21
|
+
onnx: Optional[str] = None,
|
|
22
|
+
*,
|
|
23
|
+
root: Optional[Union[str, Path]] = None,
|
|
24
|
+
allow_build_execution: bool = False,
|
|
25
|
+
):
|
|
26
|
+
self._db = db
|
|
27
|
+
self._onnx = onnx
|
|
28
|
+
self._root = Path(root) if root is not None else Path.cwd()
|
|
29
|
+
self._allow_build_execution = allow_build_execution
|
|
30
|
+
self._manager = None
|
|
31
|
+
|
|
32
|
+
async def __aenter__(self) -> "CodeRAG":
|
|
33
|
+
return self
|
|
34
|
+
|
|
35
|
+
async def __aexit__(self, *_exc) -> None:
|
|
36
|
+
await self.close()
|
|
37
|
+
|
|
38
|
+
async def close(self) -> None:
|
|
39
|
+
if self._manager is not None:
|
|
40
|
+
await self._manager.close()
|
|
41
|
+
self._manager = None
|
|
42
|
+
|
|
43
|
+
def _ensure_manager(self):
|
|
44
|
+
if self._manager is None:
|
|
45
|
+
self._manager = create_manager(
|
|
46
|
+
self._db, self._onnx, allow_build_execution=self._allow_build_execution
|
|
47
|
+
)
|
|
48
|
+
return self._manager
|
|
49
|
+
|
|
50
|
+
async def config(
|
|
51
|
+
self,
|
|
52
|
+
*,
|
|
53
|
+
url: Optional[str] = None,
|
|
54
|
+
key: Optional[str] = None,
|
|
55
|
+
model: Optional[str] = None,
|
|
56
|
+
provider: Optional[str] = None,
|
|
57
|
+
) -> DistillerConfig:
|
|
58
|
+
return load_or_update_config(url=url, key=key, model=model, provider=provider)
|
|
59
|
+
|
|
60
|
+
async def setup(self, *, force: bool = False) -> SetupResult:
|
|
61
|
+
return await run_setup(force=force)
|
|
62
|
+
|
|
63
|
+
async def sync(
|
|
64
|
+
self,
|
|
65
|
+
path: Optional[str] = None,
|
|
66
|
+
*,
|
|
67
|
+
index_all: bool = False,
|
|
68
|
+
force: bool = False,
|
|
69
|
+
) -> SyncResult:
|
|
70
|
+
if path is None and not index_all:
|
|
71
|
+
return SyncResult(status="success", indexed_files=0)
|
|
72
|
+
return await run_sync(
|
|
73
|
+
self._ensure_manager(),
|
|
74
|
+
root=self._root,
|
|
75
|
+
path=path,
|
|
76
|
+
index_all=index_all,
|
|
77
|
+
force=force,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
async def search(self, query: str, *, limit: int = 5) -> list[KnowledgeUnit]:
|
|
81
|
+
return await run_search(self._ensure_manager(), query, limit=limit)
|
|
82
|
+
|
|
83
|
+
async def api(self, library: str, *, lang: Optional[str] = None) -> ApiReport:
|
|
84
|
+
return await run_api(self._ensure_manager(), library, lang=lang)
|
|
85
|
+
|
|
86
|
+
async def rebuild(self) -> SyncResult:
|
|
87
|
+
return await run_rebuild(self._ensure_manager(), root=self._root)
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
from pydantic import BaseModel, ConfigDict
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
class SyncResult(BaseModel):
|
|
5
|
+
status: str
|
|
6
|
+
indexed_files: int
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ApiReport(BaseModel):
|
|
10
|
+
library: str
|
|
11
|
+
language: str
|
|
12
|
+
report: str
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class SetupResult(BaseModel):
|
|
16
|
+
model_config = ConfigDict(protected_namespaces=())
|
|
17
|
+
|
|
18
|
+
model_dir: str
|
|
19
|
+
downloaded: list[str]
|
|
20
|
+
skipped: list[str]
|
|
@@ -19,17 +19,19 @@ class CodeRAGManager:
|
|
|
19
19
|
Orchestrates the RAG workflow: parsing, distillation, and storage.
|
|
20
20
|
"""
|
|
21
21
|
|
|
22
|
-
def __init__(
|
|
22
|
+
def __init__( # pylint: disable=too-many-arguments,too-many-positional-arguments
|
|
23
23
|
self,
|
|
24
24
|
storage: IStorage,
|
|
25
25
|
parser: IParser,
|
|
26
26
|
intelligence: IIntelligence,
|
|
27
27
|
max_concurrency: int = MAX_CONCURRENT_TASKS,
|
|
28
|
+
allow_build_execution: bool = False,
|
|
28
29
|
):
|
|
29
30
|
self.storage = storage
|
|
30
31
|
self.parser = parser
|
|
31
32
|
self.intelligence = intelligence
|
|
32
33
|
self.max_concurrency = max_concurrency
|
|
34
|
+
self.allow_build_execution = allow_build_execution
|
|
33
35
|
self.semaphore = asyncio.Semaphore(max_concurrency)
|
|
34
36
|
self.discovery = DiscoveryManager(storage=storage)
|
|
35
37
|
|
|
@@ -41,6 +43,17 @@ class CodeRAGManager:
|
|
|
41
43
|
pom_xml = root / "pom.xml"
|
|
42
44
|
gradle_files = list(root.glob("build.gradle*"))
|
|
43
45
|
|
|
46
|
+
if not pom_xml.exists() and not gradle_files:
|
|
47
|
+
return
|
|
48
|
+
|
|
49
|
+
if not self.allow_build_execution:
|
|
50
|
+
logger.warning(
|
|
51
|
+
"Dependency sync is disabled by default because Maven/Gradle "
|
|
52
|
+
"build files are executable repository code. Use the explicit "
|
|
53
|
+
"allow_build_execution option only for trusted projects."
|
|
54
|
+
)
|
|
55
|
+
return
|
|
56
|
+
|
|
44
57
|
if pom_xml.exists():
|
|
45
58
|
await self._sync_maven(root)
|
|
46
59
|
elif gradle_files:
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import asyncio
|
|
3
|
-
import os
|
|
4
3
|
import argparse
|
|
5
4
|
import sys
|
|
6
5
|
import json
|
|
@@ -15,87 +14,66 @@ from ..storage.duckdb_impl import DuckDBStorage
|
|
|
15
14
|
from ..parsers.multi_parser import MultiParser
|
|
16
15
|
from ..intelligence.distiller import Distiller, DistillerConfig
|
|
17
16
|
from ..intelligence.embedder import Embedder, get_global_dir
|
|
18
|
-
from ..parsers.languages import EXTENSION_TO_LANGUAGE
|
|
19
17
|
from ..core.utils import validate_path
|
|
20
|
-
from ..core.exceptions import CodeRAGError
|
|
18
|
+
from ..core.exceptions import CodeRAGError
|
|
19
|
+
from ..services import sync as sync_service
|
|
20
|
+
from ..services.discovery_api import run_api
|
|
21
|
+
from ..services.search import run_search
|
|
22
|
+
from ..services.setup import run_setup
|
|
21
23
|
|
|
22
24
|
logger = logging.getLogger(__name__)
|
|
23
25
|
|
|
26
|
+
# Legacy compatibility surface: these names are imported/patched by existing
|
|
27
|
+
# integrations and tests, so they must stay resolvable on this module.
|
|
28
|
+
__all__ = [
|
|
29
|
+
"get_manager",
|
|
30
|
+
"load_ignore_patterns",
|
|
31
|
+
"should_index",
|
|
32
|
+
"sync_cmd",
|
|
33
|
+
"search_cmd",
|
|
34
|
+
"api_cmd",
|
|
35
|
+
"config_cmd",
|
|
36
|
+
"setup_cmd",
|
|
37
|
+
"rebuild_cmd",
|
|
38
|
+
"DistillerConfig",
|
|
39
|
+
"Embedder",
|
|
40
|
+
"DuckDBStorage",
|
|
41
|
+
"MultiParser",
|
|
42
|
+
"Distiller",
|
|
43
|
+
"get_global_dir",
|
|
44
|
+
"requests",
|
|
45
|
+
"validate_path",
|
|
46
|
+
"main",
|
|
47
|
+
]
|
|
48
|
+
|
|
24
49
|
|
|
25
50
|
def load_ignore_patterns() -> pathspec.PathSpec:
|
|
26
|
-
"""Loads ignore patterns from .gitignore or defaults."""
|
|
27
|
-
|
|
28
|
-
if os.path.exists(".gitignore"):
|
|
29
|
-
with open(".gitignore", "r", encoding="utf-8") as f:
|
|
30
|
-
lines = f.readlines()
|
|
31
|
-
|
|
32
|
-
common_excludes = [
|
|
33
|
-
"node_modules/",
|
|
34
|
-
"venv/",
|
|
35
|
-
".venv/",
|
|
36
|
-
"__pycache__/",
|
|
37
|
-
".git/",
|
|
38
|
-
".idea/",
|
|
39
|
-
".vscode/",
|
|
40
|
-
".onnx",
|
|
41
|
-
".db",
|
|
42
|
-
".ai/",
|
|
43
|
-
]
|
|
44
|
-
return pathspec.PathSpec.from_lines("gitignore", lines + common_excludes)
|
|
51
|
+
"""Loads ignore patterns from the current directory's .gitignore or defaults."""
|
|
52
|
+
return sync_service.load_ignore_patterns(Path.cwd())
|
|
45
53
|
|
|
46
54
|
|
|
47
55
|
def should_index(path: Path, ignore_spec: Optional[pathspec.PathSpec] = None) -> bool:
|
|
48
56
|
"""Filters files that should NOT be indexed."""
|
|
49
|
-
|
|
50
|
-
path_str = str(path).replace(os.sep, "/")
|
|
51
|
-
|
|
52
|
-
# 1. Check against ignore spec (including .gitignore and common excludes)
|
|
53
|
-
if ignore_spec and ignore_spec.match_file(path_str):
|
|
54
|
-
return False
|
|
55
|
-
|
|
56
|
-
return path.suffix.lower() in EXTENSION_TO_LANGUAGE
|
|
57
|
+
return sync_service.should_index(path, ignore_spec)
|
|
57
58
|
|
|
58
59
|
|
|
59
60
|
async def sync_cmd(args):
|
|
60
|
-
# Validate input path
|
|
61
61
|
if args.path:
|
|
62
62
|
args.path = str(validate_path(args.path))
|
|
63
63
|
|
|
64
|
-
manager = get_manager(
|
|
64
|
+
manager = get_manager(
|
|
65
|
+
args.db,
|
|
66
|
+
args.onnx,
|
|
67
|
+
allow_build_execution=getattr(args, "allow_build_execution", False),
|
|
68
|
+
)
|
|
65
69
|
try:
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if args.path:
|
|
75
|
-
target_path = Path(args.path)
|
|
76
|
-
if target_path.is_file():
|
|
77
|
-
if should_index(target_path, ignore_spec):
|
|
78
|
-
await manager.sync_file(str(target_path), force_distill=args.force)
|
|
79
|
-
else:
|
|
80
|
-
paths = [
|
|
81
|
-
str(p)
|
|
82
|
-
for p in target_path.rglob("*")
|
|
83
|
-
if p.is_file() and should_index(p, ignore_spec)
|
|
84
|
-
]
|
|
85
|
-
|
|
86
|
-
if args.verbose:
|
|
87
|
-
logger.info("Indexing %d files...", len(paths))
|
|
88
|
-
await manager.sync_project(paths, force_distill=args.force)
|
|
89
|
-
elif args.all:
|
|
90
|
-
paths = [
|
|
91
|
-
str(p)
|
|
92
|
-
for p in Path(".").rglob("*")
|
|
93
|
-
if p.is_file() and should_index(p, ignore_spec)
|
|
94
|
-
]
|
|
95
|
-
|
|
96
|
-
if args.verbose:
|
|
97
|
-
logger.info("Indexing %d files...", len(paths))
|
|
98
|
-
await manager.sync_project(paths, force_distill=args.force)
|
|
70
|
+
await sync_service.run_sync(
|
|
71
|
+
manager,
|
|
72
|
+
root=Path.cwd(),
|
|
73
|
+
path=args.path,
|
|
74
|
+
index_all=bool(args.all),
|
|
75
|
+
force=bool(args.force),
|
|
76
|
+
)
|
|
99
77
|
|
|
100
78
|
if args.json:
|
|
101
79
|
print(json.dumps({"status": "success", "indexed_files": "auto"}))
|
|
@@ -112,7 +90,7 @@ async def sync_cmd(args):
|
|
|
112
90
|
async def search_cmd(args):
|
|
113
91
|
manager = get_manager(args.db, args.onnx)
|
|
114
92
|
try:
|
|
115
|
-
results = await manager
|
|
93
|
+
results = await run_search(manager, args.query, limit=args.limit)
|
|
116
94
|
|
|
117
95
|
if args.json:
|
|
118
96
|
output = []
|
|
@@ -146,14 +124,12 @@ async def search_cmd(args):
|
|
|
146
124
|
async def api_cmd(args):
|
|
147
125
|
manager = get_manager(args.db, args.onnx)
|
|
148
126
|
try:
|
|
149
|
-
|
|
150
|
-
lang = args.lang or "python"
|
|
151
|
-
api_report = await manager.discovery.extract_api(args.library, language=lang)
|
|
127
|
+
report = await run_api(manager, args.library, lang=args.lang)
|
|
152
128
|
|
|
153
129
|
if args.json:
|
|
154
|
-
print(json.dumps({"library":
|
|
130
|
+
print(json.dumps({"library": report.library, "report": report.report}))
|
|
155
131
|
else:
|
|
156
|
-
print(
|
|
132
|
+
print(report.report)
|
|
157
133
|
except Exception as e:
|
|
158
134
|
logger.error("API discovery failed: %s", e)
|
|
159
135
|
if args.json:
|
|
@@ -196,40 +172,33 @@ def config_cmd(args):
|
|
|
196
172
|
async def setup_cmd(args):
|
|
197
173
|
"""Downloads necessary local models."""
|
|
198
174
|
global_dir = get_global_dir()
|
|
199
|
-
model_dir = global_dir / "models" / "mini-lm"
|
|
200
|
-
model_dir.mkdir(parents=True, exist_ok=True)
|
|
201
|
-
|
|
202
|
-
files = {
|
|
203
|
-
"model.onnx": "https://huggingface.co/naranor/all-MiniLM-L6-v2-onnx/resolve/main/model.onnx",
|
|
204
|
-
"tokenizer.json": "https://huggingface.co/naranor/all-MiniLM-L6-v2-onnx/resolve/main/tokenizer.json",
|
|
205
|
-
}
|
|
206
175
|
|
|
207
176
|
if not args.json:
|
|
208
177
|
print(f"Setting up agent-coderag in {global_dir}...")
|
|
209
178
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
if target_path.exists() and not args.force:
|
|
213
|
-
if not args.json:
|
|
214
|
-
print(f" {name} already exists. Skipping.")
|
|
215
|
-
continue
|
|
216
|
-
|
|
217
|
-
if not args.json:
|
|
218
|
-
print(f" Downloading {name}...")
|
|
219
|
-
tmp_path = target_path.with_suffix(".tmp")
|
|
220
|
-
try:
|
|
221
|
-
response = requests.get(url, stream=True, timeout=30)
|
|
222
|
-
response.raise_for_status()
|
|
223
|
-
with open(tmp_path, "wb") as f:
|
|
224
|
-
for chunk in response.iter_content(chunk_size=8192):
|
|
225
|
-
f.write(chunk)
|
|
226
|
-
os.replace(tmp_path, target_path)
|
|
227
|
-
except Exception as e:
|
|
228
|
-
if tmp_path.exists():
|
|
229
|
-
tmp_path.unlink()
|
|
230
|
-
if not args.json:
|
|
231
|
-
print(f" Error downloading {name}: {e}")
|
|
179
|
+
def _on_progress(event: str, name: str, error: Optional[BaseException]) -> None:
|
|
180
|
+
if args.json:
|
|
232
181
|
return
|
|
182
|
+
if event == "skipped":
|
|
183
|
+
print(f" {name} already exists. Skipping.")
|
|
184
|
+
elif event == "downloading":
|
|
185
|
+
print(f" Downloading {name}...")
|
|
186
|
+
elif event == "error":
|
|
187
|
+
print(f" Error downloading {name}: {error}")
|
|
188
|
+
|
|
189
|
+
try:
|
|
190
|
+
# Pass module-level requests.get so @patch("code_rag.entry.cli.requests.get")
|
|
191
|
+
# continues to intercept downloads in legacy CLI tests.
|
|
192
|
+
await run_setup(
|
|
193
|
+
force=args.force,
|
|
194
|
+
global_dir=global_dir,
|
|
195
|
+
on_progress=_on_progress,
|
|
196
|
+
http_get=requests.get,
|
|
197
|
+
)
|
|
198
|
+
except Exception:
|
|
199
|
+
# Legacy behaviour: per-file error already reported via on_progress;
|
|
200
|
+
# stop here without crashing or printing "Setup complete.".
|
|
201
|
+
return
|
|
233
202
|
|
|
234
203
|
if not args.json:
|
|
235
204
|
print("Setup complete.")
|
|
@@ -244,19 +213,29 @@ async def rebuild_cmd(args):
|
|
|
244
213
|
await sync_cmd(args)
|
|
245
214
|
|
|
246
215
|
|
|
247
|
-
def get_manager(
|
|
248
|
-
|
|
216
|
+
def get_manager(
|
|
217
|
+
db_path: str,
|
|
218
|
+
onnx_path: Optional[str] = None,
|
|
219
|
+
allow_build_execution: bool = False,
|
|
220
|
+
) -> CodeRAGManager:
|
|
221
|
+
"""Wires a manager from the module-level components (legacy patch points).
|
|
222
|
+
|
|
223
|
+
Mirrors ``code_rag.services.factory.create_manager`` but resolves the
|
|
224
|
+
components through this module so existing CLI tests can substitute them.
|
|
225
|
+
"""
|
|
249
226
|
config = DistillerConfig.load()
|
|
250
227
|
distiller = Distiller(config)
|
|
251
228
|
embedder = Embedder(model_path=onnx_path)
|
|
252
229
|
|
|
253
|
-
# 2. Setup Storage
|
|
254
230
|
storage = DuckDBStorage(db_path, embedder=embedder)
|
|
255
|
-
|
|
256
|
-
# 3. Setup Parser
|
|
257
231
|
parser = MultiParser()
|
|
258
232
|
|
|
259
|
-
return CodeRAGManager(
|
|
233
|
+
return CodeRAGManager(
|
|
234
|
+
storage,
|
|
235
|
+
parser,
|
|
236
|
+
distiller,
|
|
237
|
+
allow_build_execution=allow_build_execution,
|
|
238
|
+
)
|
|
260
239
|
|
|
261
240
|
|
|
262
241
|
def main():
|
|
@@ -277,6 +256,11 @@ def main():
|
|
|
277
256
|
sync.add_argument("path", nargs="?", help="File or directory to index.")
|
|
278
257
|
sync.add_argument("--all", action="store_true", help="Index all supported files.")
|
|
279
258
|
sync.add_argument("--force", action="store_true", help="Force re-distillation.")
|
|
259
|
+
sync.add_argument(
|
|
260
|
+
"--allow-build-execution",
|
|
261
|
+
action="store_true",
|
|
262
|
+
help="Execute repository Maven/Gradle build files during dependency sync (trusted projects only).",
|
|
263
|
+
)
|
|
280
264
|
|
|
281
265
|
# Search
|
|
282
266
|
search = subparsers.add_parser("search", help="Semantic search.")
|