agent-coderag 1.4.0__tar.gz → 1.5.0__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.4.0/agent_coderag.egg-info → agent_coderag-1.5.0}/PKG-INFO +4 -3
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/README.md +3 -2
- {agent_coderag-1.4.0 → agent_coderag-1.5.0/agent_coderag.egg-info}/PKG-INFO +4 -3
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/agent_coderag.egg-info/SOURCES.txt +9 -0
- agent_coderag-1.5.0/agent_coderag.egg-info/entry_points.txt +2 -0
- agent_coderag-1.5.0/code_rag/__init__.py +69 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/api/client.py +12 -2
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/core/error_codes.py +1 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/core/interfaces.py +7 -1
- agent_coderag-1.5.0/code_rag/entry/args.py +120 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/entry/cli.py +34 -127
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/intelligence/distiller.py +3 -1
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/intelligence/openai_embedder.py +3 -1
- agent_coderag-1.5.0/code_rag/parsers/multi_parser.py +46 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/parsers/tree_sitter.py +11 -6
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/paths.py +5 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/services/indexing.py +19 -2
- agent_coderag-1.5.0/code_rag/services/path_migration.py +121 -0
- agent_coderag-1.5.0/code_rag/services/search.py +20 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/services/sync.py +65 -11
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/storage/duckdb_impl.py +120 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/pyproject.toml +2 -2
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_cli_detailed.py +40 -2
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_cli_embeddings.py +2 -1
- agent_coderag-1.5.0/tests/test_cli_startup.py +123 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_distiller.py +3 -3
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_error_codes.py +4 -0
- agent_coderag-1.5.0/tests/test_gitignore_root.py +67 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_indexing_embeddings.py +1 -1
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_interfaces.py +7 -1
- agent_coderag-1.5.0/tests/test_migration_cli_e2e.py +141 -0
- agent_coderag-1.5.0/tests/test_migration_coderag.py +246 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_openai_embedder.py +12 -12
- agent_coderag-1.5.0/tests/test_path_migration.py +565 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_readme_lifetime_storage.py +1 -0
- agent_coderag-1.5.0/tests/test_relative_sync_paths.py +42 -0
- agent_coderag-1.5.0/tests/test_search_relative_paths.py +111 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_storage_embeddings.py +71 -0
- agent_coderag-1.4.0/agent_coderag.egg-info/entry_points.txt +0 -2
- agent_coderag-1.4.0/code_rag/__init__.py +0 -21
- agent_coderag-1.4.0/code_rag/parsers/multi_parser.py +0 -31
- agent_coderag-1.4.0/code_rag/services/search.py +0 -9
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/LICENSE +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/NOTICE +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/agent_coderag.egg-info/dependency_links.txt +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/agent_coderag.egg-info/requires.txt +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/agent_coderag.egg-info/top_level.txt +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/api/__init__.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/api/models.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/core/__init__.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/core/constants.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/core/exceptions.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/core/models.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/core/utils.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/__init__.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/dependency.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/java_discovery.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/manager.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/providers/__init__.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/providers/base.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/providers/csharp.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/providers/go.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/providers/java.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/providers/javascript.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/providers/python.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/discovery/providers/rust.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/entry/__init__.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/intelligence/__init__.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/intelligence/embedder.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/intelligence/factory.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/parsers/__init__.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/parsers/languages.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/services/__init__.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/services/config.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/services/dependencies.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/services/discovery_api.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/services/factory.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/services/setup.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/storage/__init__.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/code_rag/storage/db_connection.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/setup.cfg +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_api_client.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_api_lazy_db.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_api_models.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_api_rebuild_wipe.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_cli.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_cli_json_parity.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_code_rag_simple.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_coderag_lifetime.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_csharp_discovery_detailed.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_db_connection.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_db_path.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_dependency_discovery.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_discovery_manager_detailed.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_discovery_providers_extra.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_discovery_python.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_distiller_config_embedding.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_distiller_extra.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_embedder.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_embedder_detailed.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_embedder_factory.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_embedder_interface.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_embedder_stubs.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_factory_async.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_indexing_detailed.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_indexing_extra.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_js_discovery_detailed.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_languages.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_local_onnx_embedder.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_models.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_multi_parser.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_readme_library_usage.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_readme_offline_embeddings.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_rust_discovery_detailed.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_storage_detailed.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_sync_worker_errors.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/tests/test_tree_sitter_parser.py +0 -0
- {agent_coderag-1.4.0 → agent_coderag-1.5.0}/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
|
+
Version: 1.5.0
|
|
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
|
|
@@ -189,10 +189,11 @@ async def main():
|
|
|
189
189
|
- **Explicit path:** `CodeRAG(db=...)` / `agent-coderag --db ...`. Path is a **file**, not a directory. Relative paths resolve against **process cwd**, not `root`.
|
|
190
190
|
- **Sidecars:** DuckDB may write WAL sidecars (e.g. `.coderag.db.wal`) beside the index during writes; locks should not persist after an operation finishes.
|
|
191
191
|
- **Connect timeout:** `connect_timeout_seconds=5` (CLI `--connect-timeout`) waits on file locks, then raises `StorageBusyError` (`ErrorCode.STORAGE_BUSY`). Pass `0` for a single attempt.
|
|
192
|
-
- **Read-only search:** `search` (and `api` when storage is needed) opens read-only. A missing index file is an error — use `sync`/`rebuild` to create it. With `--json`, success is a hit array; errors are `{"status":"error","message":...}`
|
|
192
|
+
- **Read-only search:** `search` (and `api` when storage is needed) opens read-only. A missing **index file** is an error — use `sync`/`rebuild` to create it. An index file that exists but has no embeddings table (e.g. opened/written without a completed vector sync) raises `StorageError` with `ErrorCode.EMBEDDINGS_MISSING` — run `sync` (library: `CodeRAG.sync`) before search. With `--json`, success is a hit array; errors are `{"status":"error","message":...}` and include `"code"` when the exception carries an `ErrorCode`.
|
|
193
|
+
- **Paths:** `sync` stores paths relative to `root` (`src/a.py`). The first sync rewrites an older absolute index when the file is still under `root` or its unit hashes match a file in the tree. Search returns an absolute path under the current root. `search --relative-paths`, config `relative_paths: true`, or `CodeRAG(relative_paths=True)` returns the stored relative path. Until that sync runs, search returns the absolute path stored in the index. Ignore rules use the same project-relative path, so a `.worktrees/<name>` checkout is indexed when that directory is the root.
|
|
193
194
|
- **Lifetime:** embedder/parser/distiller stay warm; DuckDB opens per operation and closes afterward. One `CodeRAG` instance serializes overlapping ops. `config()` with embedding flags / `--clear-embedding` closes the process embedder so the next op rebuilds it; distill-only `config` refreshes Distiller and keeps the embedder.
|
|
194
195
|
- **`api()` without DB:** providers that do not need the index (e.g. Python) skip DuckDB entirely; Java uses a short read-only open for JAR cache lookup.
|
|
195
|
-
- **Errors:** catch `CodeRAGError` and inspect `.code` — `STORAGE_BUSY`, `STORAGE_CORRUPT`, `EMBEDDING_MISMATCH` (`from code_rag import ErrorCode`).
|
|
196
|
+
- **Errors:** catch `CodeRAGError` and inspect `.code` — `STORAGE_BUSY`, `STORAGE_CORRUPT`, `EMBEDDING_MISMATCH`, `EMBEDDINGS_MISSING` (`from code_rag import ErrorCode`).
|
|
196
197
|
|
|
197
198
|
---
|
|
198
199
|
|
|
@@ -143,10 +143,11 @@ async def main():
|
|
|
143
143
|
- **Explicit path:** `CodeRAG(db=...)` / `agent-coderag --db ...`. Path is a **file**, not a directory. Relative paths resolve against **process cwd**, not `root`.
|
|
144
144
|
- **Sidecars:** DuckDB may write WAL sidecars (e.g. `.coderag.db.wal`) beside the index during writes; locks should not persist after an operation finishes.
|
|
145
145
|
- **Connect timeout:** `connect_timeout_seconds=5` (CLI `--connect-timeout`) waits on file locks, then raises `StorageBusyError` (`ErrorCode.STORAGE_BUSY`). Pass `0` for a single attempt.
|
|
146
|
-
- **Read-only search:** `search` (and `api` when storage is needed) opens read-only. A missing index file is an error — use `sync`/`rebuild` to create it. With `--json`, success is a hit array; errors are `{"status":"error","message":...}`
|
|
146
|
+
- **Read-only search:** `search` (and `api` when storage is needed) opens read-only. A missing **index file** is an error — use `sync`/`rebuild` to create it. An index file that exists but has no embeddings table (e.g. opened/written without a completed vector sync) raises `StorageError` with `ErrorCode.EMBEDDINGS_MISSING` — run `sync` (library: `CodeRAG.sync`) before search. With `--json`, success is a hit array; errors are `{"status":"error","message":...}` and include `"code"` when the exception carries an `ErrorCode`.
|
|
147
|
+
- **Paths:** `sync` stores paths relative to `root` (`src/a.py`). The first sync rewrites an older absolute index when the file is still under `root` or its unit hashes match a file in the tree. Search returns an absolute path under the current root. `search --relative-paths`, config `relative_paths: true`, or `CodeRAG(relative_paths=True)` returns the stored relative path. Until that sync runs, search returns the absolute path stored in the index. Ignore rules use the same project-relative path, so a `.worktrees/<name>` checkout is indexed when that directory is the root.
|
|
147
148
|
- **Lifetime:** embedder/parser/distiller stay warm; DuckDB opens per operation and closes afterward. One `CodeRAG` instance serializes overlapping ops. `config()` with embedding flags / `--clear-embedding` closes the process embedder so the next op rebuilds it; distill-only `config` refreshes Distiller and keeps the embedder.
|
|
148
149
|
- **`api()` without DB:** providers that do not need the index (e.g. Python) skip DuckDB entirely; Java uses a short read-only open for JAR cache lookup.
|
|
149
|
-
- **Errors:** catch `CodeRAGError` and inspect `.code` — `STORAGE_BUSY`, `STORAGE_CORRUPT`, `EMBEDDING_MISMATCH` (`from code_rag import ErrorCode`).
|
|
150
|
+
- **Errors:** catch `CodeRAGError` and inspect `.code` — `STORAGE_BUSY`, `STORAGE_CORRUPT`, `EMBEDDING_MISMATCH`, `EMBEDDINGS_MISSING` (`from code_rag import ErrorCode`).
|
|
150
151
|
|
|
151
152
|
---
|
|
152
153
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-coderag
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.5.0
|
|
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
|
|
@@ -189,10 +189,11 @@ async def main():
|
|
|
189
189
|
- **Explicit path:** `CodeRAG(db=...)` / `agent-coderag --db ...`. Path is a **file**, not a directory. Relative paths resolve against **process cwd**, not `root`.
|
|
190
190
|
- **Sidecars:** DuckDB may write WAL sidecars (e.g. `.coderag.db.wal`) beside the index during writes; locks should not persist after an operation finishes.
|
|
191
191
|
- **Connect timeout:** `connect_timeout_seconds=5` (CLI `--connect-timeout`) waits on file locks, then raises `StorageBusyError` (`ErrorCode.STORAGE_BUSY`). Pass `0` for a single attempt.
|
|
192
|
-
- **Read-only search:** `search` (and `api` when storage is needed) opens read-only. A missing index file is an error — use `sync`/`rebuild` to create it. With `--json`, success is a hit array; errors are `{"status":"error","message":...}`
|
|
192
|
+
- **Read-only search:** `search` (and `api` when storage is needed) opens read-only. A missing **index file** is an error — use `sync`/`rebuild` to create it. An index file that exists but has no embeddings table (e.g. opened/written without a completed vector sync) raises `StorageError` with `ErrorCode.EMBEDDINGS_MISSING` — run `sync` (library: `CodeRAG.sync`) before search. With `--json`, success is a hit array; errors are `{"status":"error","message":...}` and include `"code"` when the exception carries an `ErrorCode`.
|
|
193
|
+
- **Paths:** `sync` stores paths relative to `root` (`src/a.py`). The first sync rewrites an older absolute index when the file is still under `root` or its unit hashes match a file in the tree. Search returns an absolute path under the current root. `search --relative-paths`, config `relative_paths: true`, or `CodeRAG(relative_paths=True)` returns the stored relative path. Until that sync runs, search returns the absolute path stored in the index. Ignore rules use the same project-relative path, so a `.worktrees/<name>` checkout is indexed when that directory is the root.
|
|
193
194
|
- **Lifetime:** embedder/parser/distiller stay warm; DuckDB opens per operation and closes afterward. One `CodeRAG` instance serializes overlapping ops. `config()` with embedding flags / `--clear-embedding` closes the process embedder so the next op rebuilds it; distill-only `config` refreshes Distiller and keeps the embedder.
|
|
194
195
|
- **`api()` without DB:** providers that do not need the index (e.g. Python) skip DuckDB entirely; Java uses a short read-only open for JAR cache lookup.
|
|
195
|
-
- **Errors:** catch `CodeRAGError` and inspect `.code` — `STORAGE_BUSY`, `STORAGE_CORRUPT`, `EMBEDDING_MISMATCH` (`from code_rag import ErrorCode`).
|
|
196
|
+
- **Errors:** catch `CodeRAGError` and inspect `.code` — `STORAGE_BUSY`, `STORAGE_CORRUPT`, `EMBEDDING_MISMATCH`, `EMBEDDINGS_MISSING` (`from code_rag import ErrorCode`).
|
|
196
197
|
|
|
197
198
|
---
|
|
198
199
|
|
|
@@ -33,6 +33,7 @@ code_rag/discovery/providers/javascript.py
|
|
|
33
33
|
code_rag/discovery/providers/python.py
|
|
34
34
|
code_rag/discovery/providers/rust.py
|
|
35
35
|
code_rag/entry/__init__.py
|
|
36
|
+
code_rag/entry/args.py
|
|
36
37
|
code_rag/entry/cli.py
|
|
37
38
|
code_rag/intelligence/__init__.py
|
|
38
39
|
code_rag/intelligence/distiller.py
|
|
@@ -49,6 +50,7 @@ code_rag/services/dependencies.py
|
|
|
49
50
|
code_rag/services/discovery_api.py
|
|
50
51
|
code_rag/services/factory.py
|
|
51
52
|
code_rag/services/indexing.py
|
|
53
|
+
code_rag/services/path_migration.py
|
|
52
54
|
code_rag/services/search.py
|
|
53
55
|
code_rag/services/setup.py
|
|
54
56
|
code_rag/services/sync.py
|
|
@@ -63,6 +65,7 @@ tests/test_cli.py
|
|
|
63
65
|
tests/test_cli_detailed.py
|
|
64
66
|
tests/test_cli_embeddings.py
|
|
65
67
|
tests/test_cli_json_parity.py
|
|
68
|
+
tests/test_cli_startup.py
|
|
66
69
|
tests/test_code_rag_simple.py
|
|
67
70
|
tests/test_coderag_lifetime.py
|
|
68
71
|
tests/test_csharp_discovery_detailed.py
|
|
@@ -82,6 +85,7 @@ tests/test_embedder_interface.py
|
|
|
82
85
|
tests/test_embedder_stubs.py
|
|
83
86
|
tests/test_error_codes.py
|
|
84
87
|
tests/test_factory_async.py
|
|
88
|
+
tests/test_gitignore_root.py
|
|
85
89
|
tests/test_indexing_detailed.py
|
|
86
90
|
tests/test_indexing_embeddings.py
|
|
87
91
|
tests/test_indexing_extra.py
|
|
@@ -89,13 +93,18 @@ tests/test_interfaces.py
|
|
|
89
93
|
tests/test_js_discovery_detailed.py
|
|
90
94
|
tests/test_languages.py
|
|
91
95
|
tests/test_local_onnx_embedder.py
|
|
96
|
+
tests/test_migration_cli_e2e.py
|
|
97
|
+
tests/test_migration_coderag.py
|
|
92
98
|
tests/test_models.py
|
|
93
99
|
tests/test_multi_parser.py
|
|
94
100
|
tests/test_openai_embedder.py
|
|
101
|
+
tests/test_path_migration.py
|
|
95
102
|
tests/test_readme_library_usage.py
|
|
96
103
|
tests/test_readme_lifetime_storage.py
|
|
97
104
|
tests/test_readme_offline_embeddings.py
|
|
105
|
+
tests/test_relative_sync_paths.py
|
|
98
106
|
tests/test_rust_discovery_detailed.py
|
|
107
|
+
tests/test_search_relative_paths.py
|
|
99
108
|
tests/test_storage_detailed.py
|
|
100
109
|
tests/test_storage_embeddings.py
|
|
101
110
|
tests/test_sync_worker_errors.py
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""Public package surface. Imports stay lazy so ``agent-coderag --help`` does not load DuckDB, ONNX, or LiteLLM."""
|
|
2
|
+
|
|
3
|
+
import importlib
|
|
4
|
+
|
|
5
|
+
# Names are assigned so static checkers accept ``__all__``, then removed so
|
|
6
|
+
# attribute access goes through ``__getattr__`` and stays lazy.
|
|
7
|
+
CodeRAG = None
|
|
8
|
+
SyncResult = None
|
|
9
|
+
ApiReport = None
|
|
10
|
+
SetupResult = None
|
|
11
|
+
KnowledgeUnit = None
|
|
12
|
+
UnitKind = None
|
|
13
|
+
DistillerConfig = None
|
|
14
|
+
CodeRAGError = None
|
|
15
|
+
ErrorCode = None
|
|
16
|
+
StorageBusyError = None
|
|
17
|
+
default_db_path = None
|
|
18
|
+
|
|
19
|
+
__all__ = [
|
|
20
|
+
"CodeRAG",
|
|
21
|
+
"SyncResult",
|
|
22
|
+
"ApiReport",
|
|
23
|
+
"SetupResult",
|
|
24
|
+
"KnowledgeUnit",
|
|
25
|
+
"UnitKind",
|
|
26
|
+
"DistillerConfig",
|
|
27
|
+
"CodeRAGError",
|
|
28
|
+
"ErrorCode",
|
|
29
|
+
"StorageBusyError",
|
|
30
|
+
"default_db_path",
|
|
31
|
+
]
|
|
32
|
+
|
|
33
|
+
_EXPORTS = {
|
|
34
|
+
"CodeRAG": ("code_rag.api.client", "CodeRAG"),
|
|
35
|
+
"SyncResult": ("code_rag.api.models", "SyncResult"),
|
|
36
|
+
"ApiReport": ("code_rag.api.models", "ApiReport"),
|
|
37
|
+
"SetupResult": ("code_rag.api.models", "SetupResult"),
|
|
38
|
+
"KnowledgeUnit": ("code_rag.core.models", "KnowledgeUnit"),
|
|
39
|
+
"UnitKind": ("code_rag.core.models", "UnitKind"),
|
|
40
|
+
"DistillerConfig": ("code_rag.intelligence.distiller", "DistillerConfig"),
|
|
41
|
+
"CodeRAGError": ("code_rag.core.exceptions", "CodeRAGError"),
|
|
42
|
+
"ErrorCode": ("code_rag.core.error_codes", "ErrorCode"),
|
|
43
|
+
"StorageBusyError": ("code_rag.core.exceptions", "StorageBusyError"),
|
|
44
|
+
"default_db_path": ("code_rag.paths", "default_db_path"),
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
del (
|
|
48
|
+
CodeRAG,
|
|
49
|
+
SyncResult,
|
|
50
|
+
ApiReport,
|
|
51
|
+
SetupResult,
|
|
52
|
+
KnowledgeUnit,
|
|
53
|
+
UnitKind,
|
|
54
|
+
DistillerConfig,
|
|
55
|
+
CodeRAGError,
|
|
56
|
+
ErrorCode,
|
|
57
|
+
StorageBusyError,
|
|
58
|
+
default_db_path,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def __getattr__(name):
|
|
63
|
+
target = _EXPORTS.get(name)
|
|
64
|
+
if target is None:
|
|
65
|
+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
|
|
66
|
+
module_name, attr = target
|
|
67
|
+
value = getattr(importlib.import_module(module_name), attr)
|
|
68
|
+
globals()[name] = value
|
|
69
|
+
return value
|
|
@@ -19,7 +19,7 @@ from code_rag.services.config import (
|
|
|
19
19
|
)
|
|
20
20
|
from code_rag.services.discovery_api import run_api
|
|
21
21
|
from code_rag.services.factory import create_stack
|
|
22
|
-
from code_rag.services.search import run_search
|
|
22
|
+
from code_rag.services.search import format_unit_path, run_search
|
|
23
23
|
from code_rag.services.setup import run_setup
|
|
24
24
|
from code_rag.services.indexing import IndexStack
|
|
25
25
|
from code_rag.services.sync import SyncOptions, run_rebuild, run_sync
|
|
@@ -40,12 +40,17 @@ class CodeRAG: # pylint: disable=too-many-instance-attributes
|
|
|
40
40
|
root: Optional[Union[str, Path]] = None,
|
|
41
41
|
allow_build_execution: bool = False,
|
|
42
42
|
connect_timeout_seconds: float = DEFAULT_CONNECT_TIMEOUT_SECONDS,
|
|
43
|
+
relative_paths: bool | None = None,
|
|
43
44
|
):
|
|
44
45
|
self._onnx = onnx
|
|
45
46
|
self._root = Path(root) if root is not None else Path.cwd()
|
|
46
47
|
self._allow_build_execution = allow_build_execution
|
|
47
48
|
self._connect_timeout_seconds = connect_timeout_seconds
|
|
48
49
|
self._db_path = resolve_db_path(db, root=self._root)
|
|
50
|
+
if relative_paths is None:
|
|
51
|
+
self._relative_paths = bool(DistillerConfig.load().relative_paths)
|
|
52
|
+
else:
|
|
53
|
+
self._relative_paths = relative_paths
|
|
49
54
|
self._embedder: Optional[IEmbedder] = None
|
|
50
55
|
self._parser: Optional[IParser] = None
|
|
51
56
|
self._distiller: Optional[IIntelligence] = None
|
|
@@ -199,7 +204,12 @@ class CodeRAG: # pylint: disable=too-many-instance-attributes
|
|
|
199
204
|
|
|
200
205
|
async def search(self, query: str, *, limit: int = 5) -> list[KnowledgeUnit]:
|
|
201
206
|
async with self._with_storage(AccessMode.READ_ONLY) as storage:
|
|
202
|
-
|
|
207
|
+
units = await run_search(storage, query, limit=limit)
|
|
208
|
+
for unit in units:
|
|
209
|
+
unit.path = format_unit_path(
|
|
210
|
+
unit.path, root=self._root, relative_paths=self._relative_paths
|
|
211
|
+
)
|
|
212
|
+
return units
|
|
203
213
|
|
|
204
214
|
async def _api_java(
|
|
205
215
|
self,
|
|
@@ -7,7 +7,13 @@ class IParser(ABC):
|
|
|
7
7
|
"""Interface for extracting structure from code."""
|
|
8
8
|
|
|
9
9
|
@abstractmethod
|
|
10
|
-
async def distill_file(
|
|
10
|
+
async def distill_file(
|
|
11
|
+
self,
|
|
12
|
+
file_path: str,
|
|
13
|
+
*,
|
|
14
|
+
stored_path: str | None = None,
|
|
15
|
+
raise_on_failure: bool = False,
|
|
16
|
+
) -> List[KnowledgeUnit]:
|
|
11
17
|
pass # pragma: no cover
|
|
12
18
|
|
|
13
19
|
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""Argparse entry. Importing this module must stay free of DuckDB, ONNX, and LiteLLM."""
|
|
2
|
+
|
|
3
|
+
import argparse
|
|
4
|
+
import importlib
|
|
5
|
+
import logging
|
|
6
|
+
import sys
|
|
7
|
+
|
|
8
|
+
from code_rag.core.constants import DEFAULT_CONNECT_TIMEOUT_SECONDS
|
|
9
|
+
from code_rag.core.exceptions import CodeRAGError
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def build_parser() -> argparse.ArgumentParser:
|
|
13
|
+
parser = argparse.ArgumentParser(description="CodeRAG: API Knowledge Bridge.")
|
|
14
|
+
parser.add_argument(
|
|
15
|
+
"--db",
|
|
16
|
+
default=None,
|
|
17
|
+
help=(
|
|
18
|
+
"DuckDB index file. Default: resolve legacy code_rag.db in cwd/root, "
|
|
19
|
+
"else use .coderag.db under project root."
|
|
20
|
+
),
|
|
21
|
+
)
|
|
22
|
+
parser.add_argument("--onnx", help="Path to local ONNX model file.")
|
|
23
|
+
parser.add_argument(
|
|
24
|
+
"--connect-timeout",
|
|
25
|
+
dest="connect_timeout",
|
|
26
|
+
type=float,
|
|
27
|
+
default=DEFAULT_CONNECT_TIMEOUT_SECONDS,
|
|
28
|
+
help=(
|
|
29
|
+
"Seconds to wait for a DuckDB file lock before StorageBusyError "
|
|
30
|
+
f"(default {DEFAULT_CONNECT_TIMEOUT_SECONDS:g}). 0 = no retry."
|
|
31
|
+
),
|
|
32
|
+
)
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
"--verbose", action="store_true", help="Enable verbose logging."
|
|
35
|
+
)
|
|
36
|
+
parser.add_argument("--json", action="store_true", help="Output results in JSON.")
|
|
37
|
+
|
|
38
|
+
subparsers = parser.add_subparsers(dest="command")
|
|
39
|
+
|
|
40
|
+
sync = subparsers.add_parser("sync", help="Index code units.")
|
|
41
|
+
sync.add_argument("path", nargs="?", help="File or directory to index.")
|
|
42
|
+
sync.add_argument("--all", action="store_true", help="Index all supported files.")
|
|
43
|
+
sync.add_argument("--force", action="store_true", help="Force re-distillation.")
|
|
44
|
+
sync.add_argument(
|
|
45
|
+
"--allow-build-execution",
|
|
46
|
+
action="store_true",
|
|
47
|
+
help="Execute repository Maven/Gradle build files during dependency sync (trusted projects only).",
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
search = subparsers.add_parser("search", help="Semantic search.")
|
|
51
|
+
search.add_argument("query", help="Natural language query.")
|
|
52
|
+
search.add_argument("--limit", type=int, default=5, help="Result limit.")
|
|
53
|
+
search.add_argument(
|
|
54
|
+
"--relative-paths",
|
|
55
|
+
dest="relative_paths",
|
|
56
|
+
action="store_true",
|
|
57
|
+
default=None,
|
|
58
|
+
help="Print paths relative to the project root. Default: absolute paths under the current root.",
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
api = subparsers.add_parser("api", help="Discover library API.")
|
|
62
|
+
api.add_argument("library", help="Library name (e.g., pydantic).")
|
|
63
|
+
api.add_argument("--lang", help="Target language.")
|
|
64
|
+
|
|
65
|
+
cfg = subparsers.add_parser("config", help="Manage LLM configuration.")
|
|
66
|
+
cfg.add_argument("--url", help="API base URL.")
|
|
67
|
+
cfg.add_argument("--key", help="API key.")
|
|
68
|
+
cfg.add_argument("--model", help="Model name.")
|
|
69
|
+
cfg.add_argument("--provider", help="Provider name (openai, ollama).")
|
|
70
|
+
cfg.add_argument(
|
|
71
|
+
"--embedding-url", dest="embedding_url", help="Embedding API base URL."
|
|
72
|
+
)
|
|
73
|
+
cfg.add_argument("--embedding-key", dest="embedding_key", help="Embedding API key.")
|
|
74
|
+
cfg.add_argument(
|
|
75
|
+
"--embedding-model", dest="embedding_model", help="Remote embedding model id."
|
|
76
|
+
)
|
|
77
|
+
cfg.add_argument(
|
|
78
|
+
"--embedding-provider",
|
|
79
|
+
dest="embedding_provider",
|
|
80
|
+
help="LiteLLM custom_llm_provider for embeddings.",
|
|
81
|
+
)
|
|
82
|
+
cfg.add_argument(
|
|
83
|
+
"--clear-embedding",
|
|
84
|
+
dest="clear_embedding",
|
|
85
|
+
action="store_true",
|
|
86
|
+
help="Clear remote embedding config (local MiniLM).",
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
setup = subparsers.add_parser("setup", help="Initial setup (download models).")
|
|
90
|
+
setup.add_argument("--force", action="store_true", help="Force model redownload.")
|
|
91
|
+
|
|
92
|
+
subparsers.add_parser("rebuild", help="Full re-index of the project.")
|
|
93
|
+
return parser
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def main() -> None:
|
|
97
|
+
parser = build_parser()
|
|
98
|
+
try:
|
|
99
|
+
args = parser.parse_args()
|
|
100
|
+
|
|
101
|
+
if args.verbose:
|
|
102
|
+
logging.basicConfig(level=logging.INFO)
|
|
103
|
+
else:
|
|
104
|
+
logging.basicConfig(level=logging.WARNING)
|
|
105
|
+
|
|
106
|
+
if not args.command:
|
|
107
|
+
parser.print_help()
|
|
108
|
+
return
|
|
109
|
+
|
|
110
|
+
# Heavy stack (DuckDB, ONNX, parsers) loads only for a real subcommand.
|
|
111
|
+
dispatch = importlib.import_module("code_rag.entry.cli").dispatch
|
|
112
|
+
dispatch(args)
|
|
113
|
+
except CodeRAGError as exc:
|
|
114
|
+
print(f"Error: {exc}", file=sys.stderr)
|
|
115
|
+
sys.exit(1)
|
|
116
|
+
except KeyboardInterrupt:
|
|
117
|
+
sys.exit(0)
|
|
118
|
+
except Exception as exc:
|
|
119
|
+
logging.getLogger(__name__).error("Unexpected error: %s", exc)
|
|
120
|
+
sys.exit(1)
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import asyncio
|
|
3
|
-
import argparse
|
|
4
3
|
import sys
|
|
5
4
|
import json
|
|
6
5
|
from pathlib import Path
|
|
@@ -43,11 +42,11 @@ __all__ = [
|
|
|
43
42
|
"get_global_dir",
|
|
44
43
|
"requests",
|
|
45
44
|
"validate_path",
|
|
46
|
-
"main",
|
|
47
45
|
]
|
|
48
46
|
|
|
49
47
|
|
|
50
48
|
def _coderag_from_args(args) -> CodeRAG:
|
|
49
|
+
relative_paths = getattr(args, "relative_paths", None)
|
|
51
50
|
return CodeRAG(
|
|
52
51
|
db=args.db,
|
|
53
52
|
onnx=getattr(args, "onnx", None),
|
|
@@ -56,17 +55,31 @@ def _coderag_from_args(args) -> CodeRAG:
|
|
|
56
55
|
getattr(args, "connect_timeout", DEFAULT_CONNECT_TIMEOUT_SECONDS)
|
|
57
56
|
),
|
|
58
57
|
allow_build_execution=bool(getattr(args, "allow_build_execution", False)),
|
|
58
|
+
relative_paths=True if relative_paths else None,
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
|
|
62
|
+
def _emit_json_error(exc: Exception) -> None:
|
|
63
|
+
payload = {"status": "error", "message": str(exc)}
|
|
64
|
+
code = getattr(exc, "code", None)
|
|
65
|
+
if isinstance(exc, CodeRAGError) and code is not None:
|
|
66
|
+
payload["code"] = code.value if hasattr(code, "value") else str(code)
|
|
67
|
+
print(json.dumps(payload))
|
|
68
|
+
|
|
69
|
+
|
|
62
70
|
def load_ignore_patterns() -> pathspec.PathSpec:
|
|
63
71
|
"""Loads ignore patterns from the current directory's .gitignore or defaults."""
|
|
64
72
|
return sync_service.load_ignore_patterns(Path.cwd())
|
|
65
73
|
|
|
66
74
|
|
|
67
|
-
def should_index(
|
|
75
|
+
def should_index(
|
|
76
|
+
path: Path,
|
|
77
|
+
ignore_spec: Optional[pathspec.PathSpec] = None,
|
|
78
|
+
*,
|
|
79
|
+
root: Optional[Path] = None,
|
|
80
|
+
) -> bool:
|
|
68
81
|
"""Filters files that should NOT be indexed."""
|
|
69
|
-
return sync_service.should_index(path, ignore_spec)
|
|
82
|
+
return sync_service.should_index(path, ignore_spec, root=root)
|
|
70
83
|
|
|
71
84
|
|
|
72
85
|
def _emit_sync_outcome(result: SyncResult, *, json_mode: bool, label: str) -> None:
|
|
@@ -105,7 +118,7 @@ async def sync_cmd(args):
|
|
|
105
118
|
except Exception as e:
|
|
106
119
|
logger.error("Sync failed: %s", e)
|
|
107
120
|
if args.json:
|
|
108
|
-
|
|
121
|
+
_emit_json_error(e)
|
|
109
122
|
else:
|
|
110
123
|
print(f"Error: {e}", file=sys.stderr)
|
|
111
124
|
raise SystemExit(1) from e
|
|
@@ -146,7 +159,7 @@ async def search_cmd(args):
|
|
|
146
159
|
except Exception as e:
|
|
147
160
|
logger.error("Search failed: %s", e)
|
|
148
161
|
if args.json:
|
|
149
|
-
|
|
162
|
+
_emit_json_error(e)
|
|
150
163
|
else:
|
|
151
164
|
print(f"Error: {e}", file=sys.stderr)
|
|
152
165
|
raise SystemExit(1) from e
|
|
@@ -166,7 +179,7 @@ async def api_cmd(args):
|
|
|
166
179
|
except Exception as e:
|
|
167
180
|
logger.error("API discovery failed: %s", e)
|
|
168
181
|
if args.json:
|
|
169
|
-
|
|
182
|
+
_emit_json_error(e)
|
|
170
183
|
else:
|
|
171
184
|
print(f"Error: {e}", file=sys.stderr)
|
|
172
185
|
finally:
|
|
@@ -277,7 +290,7 @@ async def rebuild_cmd(args):
|
|
|
277
290
|
except Exception as exc:
|
|
278
291
|
logger.error("Rebuild failed: %s", exc)
|
|
279
292
|
if args.json:
|
|
280
|
-
|
|
293
|
+
_emit_json_error(exc)
|
|
281
294
|
else:
|
|
282
295
|
print(f"Error: {exc}", file=sys.stderr)
|
|
283
296
|
raise SystemExit(1) from exc
|
|
@@ -285,122 +298,16 @@ async def rebuild_cmd(args):
|
|
|
285
298
|
await rag.close()
|
|
286
299
|
|
|
287
300
|
|
|
288
|
-
def
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
)
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
dest="connect_timeout",
|
|
302
|
-
type=float,
|
|
303
|
-
default=DEFAULT_CONNECT_TIMEOUT_SECONDS,
|
|
304
|
-
help=(
|
|
305
|
-
"Seconds to wait for a DuckDB file lock before StorageBusyError "
|
|
306
|
-
f"(default {DEFAULT_CONNECT_TIMEOUT_SECONDS:g}). 0 = no retry."
|
|
307
|
-
),
|
|
308
|
-
)
|
|
309
|
-
parser.add_argument(
|
|
310
|
-
"--verbose", action="store_true", help="Enable verbose logging."
|
|
311
|
-
)
|
|
312
|
-
parser.add_argument("--json", action="store_true", help="Output results in JSON.")
|
|
313
|
-
|
|
314
|
-
subparsers = parser.add_subparsers(dest="command")
|
|
315
|
-
|
|
316
|
-
# Sync
|
|
317
|
-
sync = subparsers.add_parser("sync", help="Index code units.")
|
|
318
|
-
sync.add_argument("path", nargs="?", help="File or directory to index.")
|
|
319
|
-
sync.add_argument("--all", action="store_true", help="Index all supported files.")
|
|
320
|
-
sync.add_argument("--force", action="store_true", help="Force re-distillation.")
|
|
321
|
-
sync.add_argument(
|
|
322
|
-
"--allow-build-execution",
|
|
323
|
-
action="store_true",
|
|
324
|
-
help="Execute repository Maven/Gradle build files during dependency sync (trusted projects only).",
|
|
325
|
-
)
|
|
326
|
-
|
|
327
|
-
# Search
|
|
328
|
-
search = subparsers.add_parser("search", help="Semantic search.")
|
|
329
|
-
search.add_argument("query", help="Natural language query.")
|
|
330
|
-
search.add_argument("--limit", type=int, default=5, help="Result limit.")
|
|
331
|
-
|
|
332
|
-
# API
|
|
333
|
-
api = subparsers.add_parser("api", help="Discover library API.")
|
|
334
|
-
api.add_argument("library", help="Library name (e.g., pydantic).")
|
|
335
|
-
api.add_argument("--lang", help="Target language.")
|
|
336
|
-
|
|
337
|
-
# Config
|
|
338
|
-
cfg = subparsers.add_parser("config", help="Manage LLM configuration.")
|
|
339
|
-
cfg.add_argument("--url", help="API base URL.")
|
|
340
|
-
cfg.add_argument("--key", help="API key.")
|
|
341
|
-
cfg.add_argument("--model", help="Model name.")
|
|
342
|
-
cfg.add_argument("--provider", help="Provider name (openai, ollama).")
|
|
343
|
-
cfg.add_argument(
|
|
344
|
-
"--embedding-url", dest="embedding_url", help="Embedding API base URL."
|
|
345
|
-
)
|
|
346
|
-
cfg.add_argument("--embedding-key", dest="embedding_key", help="Embedding API key.")
|
|
347
|
-
cfg.add_argument(
|
|
348
|
-
"--embedding-model", dest="embedding_model", help="Remote embedding model id."
|
|
349
|
-
)
|
|
350
|
-
cfg.add_argument(
|
|
351
|
-
"--embedding-provider",
|
|
352
|
-
dest="embedding_provider",
|
|
353
|
-
help="LiteLLM custom_llm_provider for embeddings.",
|
|
354
|
-
)
|
|
355
|
-
cfg.add_argument(
|
|
356
|
-
"--clear-embedding",
|
|
357
|
-
dest="clear_embedding",
|
|
358
|
-
action="store_true",
|
|
359
|
-
help="Clear remote embedding config (local MiniLM).",
|
|
360
|
-
)
|
|
361
|
-
|
|
362
|
-
# Setup
|
|
363
|
-
setup = subparsers.add_parser("setup", help="Initial setup (download models).")
|
|
364
|
-
setup.add_argument("--force", action="store_true", help="Force model redownload.")
|
|
365
|
-
|
|
366
|
-
# Rebuild
|
|
367
|
-
subparsers.add_parser("rebuild", help="Full re-index of the project.")
|
|
368
|
-
return parser
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
def main():
|
|
372
|
-
parser = _build_arg_parser()
|
|
373
|
-
try:
|
|
374
|
-
args = parser.parse_args()
|
|
375
|
-
|
|
376
|
-
if args.verbose:
|
|
377
|
-
logging.basicConfig(level=logging.INFO)
|
|
378
|
-
else:
|
|
379
|
-
logging.basicConfig(level=logging.WARNING)
|
|
380
|
-
|
|
381
|
-
if args.command == "sync":
|
|
382
|
-
asyncio.run(sync_cmd(args))
|
|
383
|
-
elif args.command == "search":
|
|
384
|
-
asyncio.run(search_cmd(args))
|
|
385
|
-
elif args.command == "api":
|
|
386
|
-
asyncio.run(api_cmd(args))
|
|
387
|
-
elif args.command == "config":
|
|
388
|
-
config_cmd(args)
|
|
389
|
-
elif args.command == "setup":
|
|
390
|
-
asyncio.run(setup_cmd(args))
|
|
391
|
-
elif args.command == "rebuild":
|
|
392
|
-
asyncio.run(rebuild_cmd(args))
|
|
393
|
-
else:
|
|
394
|
-
parser.print_help()
|
|
395
|
-
except CodeRAGError as e:
|
|
396
|
-
print(f"Error: {e}", file=sys.stderr)
|
|
397
|
-
sys.exit(1)
|
|
398
|
-
except KeyboardInterrupt:
|
|
399
|
-
sys.exit(0)
|
|
400
|
-
except Exception as e:
|
|
401
|
-
logger.error("Unexpected error: %s", e)
|
|
402
|
-
sys.exit(1)
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
if __name__ == "__main__":
|
|
406
|
-
main()
|
|
301
|
+
def dispatch(args) -> None:
|
|
302
|
+
if args.command == "sync":
|
|
303
|
+
asyncio.run(sync_cmd(args))
|
|
304
|
+
elif args.command == "search":
|
|
305
|
+
asyncio.run(search_cmd(args))
|
|
306
|
+
elif args.command == "api":
|
|
307
|
+
asyncio.run(api_cmd(args))
|
|
308
|
+
elif args.command == "config":
|
|
309
|
+
config_cmd(args)
|
|
310
|
+
elif args.command == "setup":
|
|
311
|
+
asyncio.run(setup_cmd(args))
|
|
312
|
+
elif args.command == "rebuild":
|
|
313
|
+
asyncio.run(rebuild_cmd(args))
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import json
|
|
3
|
+
import importlib
|
|
3
4
|
from typing import Optional
|
|
4
|
-
import litellm
|
|
5
5
|
from pydantic import BaseModel, ConfigDict, field_validator
|
|
6
6
|
from ..core.exceptions import IntelligenceError
|
|
7
7
|
from ..core.interfaces import IIntelligence
|
|
@@ -23,6 +23,7 @@ class DistillerConfig(BaseModel):
|
|
|
23
23
|
embedding_key: Optional[str] = None
|
|
24
24
|
embedding_model: Optional[str] = None
|
|
25
25
|
embedding_provider: Optional[str] = None
|
|
26
|
+
relative_paths: bool = False
|
|
26
27
|
|
|
27
28
|
@field_validator(
|
|
28
29
|
"model",
|
|
@@ -114,6 +115,7 @@ SUMMARY:
|
|
|
114
115
|
if self.config.provider == "ollama" and not model_id.startswith("ollama/"):
|
|
115
116
|
model_id = f"ollama/{model_id}"
|
|
116
117
|
|
|
118
|
+
litellm = importlib.import_module("litellm")
|
|
117
119
|
response = await litellm.acompletion(
|
|
118
120
|
model=model_id,
|
|
119
121
|
messages=[{"role": "user", "content": prompt}],
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import asyncio
|
|
2
|
+
import importlib
|
|
2
3
|
import logging
|
|
3
4
|
from typing import Optional
|
|
4
5
|
|
|
5
|
-
import litellm
|
|
6
6
|
import numpy as np
|
|
7
7
|
|
|
8
8
|
from ..core.constants import EMBEDDING_REQUEST_TIMEOUT
|
|
@@ -74,6 +74,8 @@ class OpenAICompatEmbedder(IEmbedder):
|
|
|
74
74
|
}
|
|
75
75
|
if self._provider is not None:
|
|
76
76
|
kwargs["custom_llm_provider"] = self._provider
|
|
77
|
+
litellm = importlib.import_module("litellm")
|
|
78
|
+
|
|
77
79
|
async with self._embed_lock:
|
|
78
80
|
try:
|
|
79
81
|
response = await litellm.aembedding(**kwargs)
|