cocoindex-code 0.2.7__tar.gz → 0.2.8__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.
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/PKG-INFO +34 -1
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/README.md +33 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/_version.py +2 -2
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/cli.py +14 -2
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/config.py +4 -2
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/daemon.py +9 -1
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/project.py +9 -5
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/protocol.py +6 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/settings.py +78 -2
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/.gitignore +0 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/LICENSE +0 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/pyproject.toml +0 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/__init__.py +0 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/__main__.py +0 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/client.py +0 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/indexer.py +0 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/query.py +0 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/schema.py +0 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/server.py +0 -0
- {cocoindex_code-0.2.7 → cocoindex_code-0.2.8}/src/cocoindex_code/shared.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: cocoindex-code
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.8
|
|
4
4
|
Summary: MCP server for indexing and querying codebases using CocoIndex
|
|
5
5
|
Project-URL: Homepage, https://github.com/cocoindex-io/cocoindex-code
|
|
6
6
|
Project-URL: Repository, https://github.com/cocoindex-io/cocoindex-code
|
|
@@ -457,6 +457,26 @@ embedding:
|
|
|
457
457
|
| xml | | `.xml` |
|
|
458
458
|
| yaml | | `.yaml`, `.yml` |
|
|
459
459
|
|
|
460
|
+
### Custom Database Location
|
|
461
|
+
|
|
462
|
+
By default, index databases (`cocoindex.db` and `target_sqlite.db`) live alongside settings in `<project>/.cocoindex_code/`. When running in Docker, you may want the databases on the container's native filesystem for performance (LMDB doesn't work well on mounted volumes) while keeping the source code and settings on a mounted volume.
|
|
463
|
+
|
|
464
|
+
Set `COCOINDEX_CODE_DB_PATH_MAPPING` to remap database locations by path prefix:
|
|
465
|
+
|
|
466
|
+
```bash
|
|
467
|
+
COCOINDEX_CODE_DB_PATH_MAPPING=/workspace=/db-files
|
|
468
|
+
```
|
|
469
|
+
|
|
470
|
+
With this mapping, a project at `/workspace/myrepo` stores its databases in `/db-files/myrepo/` instead of `/workspace/myrepo/.cocoindex_code/`. Settings files remain in the original location.
|
|
471
|
+
|
|
472
|
+
Multiple mappings are comma-separated and resolved in order (first match wins):
|
|
473
|
+
|
|
474
|
+
```bash
|
|
475
|
+
COCOINDEX_CODE_DB_PATH_MAPPING=/workspace=/db-files,/workspace2=/db-files2
|
|
476
|
+
```
|
|
477
|
+
|
|
478
|
+
Both source and target must be absolute paths. If no mapping matches, the default location is used.
|
|
479
|
+
|
|
460
480
|
## Troubleshooting
|
|
461
481
|
|
|
462
482
|
Run `ccc doctor` to diagnose common issues. It checks your settings, daemon health, embedding model, file matching, and index status — all in one command.
|
|
@@ -501,6 +521,19 @@ If you previously configured `cocoindex-code` via environment variables, the `co
|
|
|
501
521
|
|
|
502
522
|
If you need help with remote setup, please email our maintainer linghua@cocoindex.io, happy to help!
|
|
503
523
|
|
|
524
|
+
## Contributing
|
|
525
|
+
|
|
526
|
+
We welcome contributions! Before you start, please install the [pre-commit](https://pre-commit.com/) hooks so that linting, formatting, type checking, and tests run automatically before each commit:
|
|
527
|
+
|
|
528
|
+
```bash
|
|
529
|
+
pip install pre-commit
|
|
530
|
+
pre-commit install
|
|
531
|
+
```
|
|
532
|
+
|
|
533
|
+
This catches common issues — trailing whitespace, lint errors (Ruff), type errors (mypy), and test failures — before they reach CI.
|
|
534
|
+
|
|
535
|
+
For more details, see our [contributing guide](https://cocoindex.io/docs/contributing/guide).
|
|
536
|
+
|
|
504
537
|
## License
|
|
505
538
|
|
|
506
539
|
Apache-2.0
|
|
@@ -418,6 +418,26 @@ embedding:
|
|
|
418
418
|
| xml | | `.xml` |
|
|
419
419
|
| yaml | | `.yaml`, `.yml` |
|
|
420
420
|
|
|
421
|
+
### Custom Database Location
|
|
422
|
+
|
|
423
|
+
By default, index databases (`cocoindex.db` and `target_sqlite.db`) live alongside settings in `<project>/.cocoindex_code/`. When running in Docker, you may want the databases on the container's native filesystem for performance (LMDB doesn't work well on mounted volumes) while keeping the source code and settings on a mounted volume.
|
|
424
|
+
|
|
425
|
+
Set `COCOINDEX_CODE_DB_PATH_MAPPING` to remap database locations by path prefix:
|
|
426
|
+
|
|
427
|
+
```bash
|
|
428
|
+
COCOINDEX_CODE_DB_PATH_MAPPING=/workspace=/db-files
|
|
429
|
+
```
|
|
430
|
+
|
|
431
|
+
With this mapping, a project at `/workspace/myrepo` stores its databases in `/db-files/myrepo/` instead of `/workspace/myrepo/.cocoindex_code/`. Settings files remain in the original location.
|
|
432
|
+
|
|
433
|
+
Multiple mappings are comma-separated and resolved in order (first match wins):
|
|
434
|
+
|
|
435
|
+
```bash
|
|
436
|
+
COCOINDEX_CODE_DB_PATH_MAPPING=/workspace=/db-files,/workspace2=/db-files2
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
Both source and target must be absolute paths. If no mapping matches, the default location is used.
|
|
440
|
+
|
|
421
441
|
## Troubleshooting
|
|
422
442
|
|
|
423
443
|
Run `ccc doctor` to diagnose common issues. It checks your settings, daemon health, embedding model, file matching, and index status — all in one command.
|
|
@@ -462,6 +482,19 @@ If you previously configured `cocoindex-code` via environment variables, the `co
|
|
|
462
482
|
|
|
463
483
|
If you need help with remote setup, please email our maintainer linghua@cocoindex.io, happy to help!
|
|
464
484
|
|
|
485
|
+
## Contributing
|
|
486
|
+
|
|
487
|
+
We welcome contributions! Before you start, please install the [pre-commit](https://pre-commit.com/) hooks so that linting, formatting, type checking, and tests run automatically before each commit:
|
|
488
|
+
|
|
489
|
+
```bash
|
|
490
|
+
pip install pre-commit
|
|
491
|
+
pre-commit install
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
This catches common issues — trailing whitespace, lint errors (Ruff), type errors (mypy), and test failures — before they reach CI.
|
|
495
|
+
|
|
496
|
+
For more details, see our [contributing guide](https://cocoindex.io/docs/contributing/guide).
|
|
497
|
+
|
|
465
498
|
## License
|
|
466
499
|
|
|
467
500
|
Apache-2.0
|
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.2.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 2,
|
|
31
|
+
__version__ = version = '0.2.8'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 2, 8)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
|
@@ -16,6 +16,7 @@ from .settings import (
|
|
|
16
16
|
default_user_settings,
|
|
17
17
|
find_parent_with_marker,
|
|
18
18
|
find_project_root,
|
|
19
|
+
resolve_db_dir,
|
|
19
20
|
save_project_settings,
|
|
20
21
|
save_user_settings,
|
|
21
22
|
user_settings_path,
|
|
@@ -389,10 +390,11 @@ def reset(
|
|
|
389
390
|
"""Reset project databases and optionally remove settings."""
|
|
390
391
|
project_root = require_project_root()
|
|
391
392
|
cocoindex_dir = project_root / ".cocoindex_code"
|
|
393
|
+
db_dir = resolve_db_dir(project_root)
|
|
392
394
|
|
|
393
395
|
db_files = [
|
|
394
|
-
|
|
395
|
-
|
|
396
|
+
db_dir / "cocoindex.db",
|
|
397
|
+
db_dir / "target_sqlite.db",
|
|
396
398
|
]
|
|
397
399
|
settings_file = cocoindex_dir / "settings.yml"
|
|
398
400
|
|
|
@@ -436,6 +438,12 @@ def reset(
|
|
|
436
438
|
f.unlink(missing_ok=True)
|
|
437
439
|
|
|
438
440
|
if all_:
|
|
441
|
+
# Remove db_dir if empty and different from cocoindex_dir
|
|
442
|
+
if db_dir != cocoindex_dir:
|
|
443
|
+
try:
|
|
444
|
+
db_dir.rmdir()
|
|
445
|
+
except OSError:
|
|
446
|
+
pass # Not empty or doesn't exist
|
|
439
447
|
# Remove .cocoindex_code/ if empty
|
|
440
448
|
try:
|
|
441
449
|
cocoindex_dir.rmdir()
|
|
@@ -539,6 +547,10 @@ def doctor() -> None:
|
|
|
539
547
|
other_keys = [k for k in env_resp.env_names if k not in settings_keys]
|
|
540
548
|
if other_keys:
|
|
541
549
|
_typer.echo(f" Other env vars in daemon: {', '.join(sorted(other_keys))}")
|
|
550
|
+
if env_resp.db_path_mappings:
|
|
551
|
+
_typer.echo(" DB path mappings:")
|
|
552
|
+
for m in env_resp.db_path_mappings:
|
|
553
|
+
_typer.echo(f" {m.source} \u2192 {m.target}")
|
|
542
554
|
except Exception as e:
|
|
543
555
|
_print_error(f"Failed to get daemon env: {e}")
|
|
544
556
|
|
|
@@ -7,6 +7,8 @@ import os
|
|
|
7
7
|
from dataclasses import dataclass
|
|
8
8
|
from pathlib import Path
|
|
9
9
|
|
|
10
|
+
from .settings import resolve_db_dir
|
|
11
|
+
|
|
10
12
|
_DEFAULT_MODEL = "sbert/sentence-transformers/all-MiniLM-L6-v2"
|
|
11
13
|
|
|
12
14
|
|
|
@@ -96,8 +98,8 @@ class Config:
|
|
|
96
98
|
_DEFAULT_MODEL,
|
|
97
99
|
)
|
|
98
100
|
|
|
99
|
-
# Index directory
|
|
100
|
-
index_dir = root
|
|
101
|
+
# Index directory: apply DB path mapping if configured
|
|
102
|
+
index_dir = resolve_db_dir(root)
|
|
101
103
|
|
|
102
104
|
# Device: auto-detect CUDA or use env override
|
|
103
105
|
device = os.environ.get("COCOINDEX_CODE_DEVICE")
|
|
@@ -48,6 +48,7 @@ from .protocol import (
|
|
|
48
48
|
from .settings import (
|
|
49
49
|
global_settings_mtime_us,
|
|
50
50
|
load_user_settings,
|
|
51
|
+
resolve_db_dir,
|
|
51
52
|
user_settings_dir,
|
|
52
53
|
)
|
|
53
54
|
from .shared import Embedder, create_embedder
|
|
@@ -345,7 +346,7 @@ async def _check_index_status(project_root_str: str) -> DoctorCheckResult:
|
|
|
345
346
|
from cocoindex.connectors import sqlite as coco_sqlite
|
|
346
347
|
|
|
347
348
|
project_root = Path(project_root_str)
|
|
348
|
-
db_path = project_root / "
|
|
349
|
+
db_path = resolve_db_dir(project_root) / "target_sqlite.db"
|
|
349
350
|
details = [f"Index: {db_path}"]
|
|
350
351
|
|
|
351
352
|
if not db_path.exists():
|
|
@@ -441,9 +442,16 @@ async def _dispatch(
|
|
|
441
442
|
return StopResponse(ok=True)
|
|
442
443
|
|
|
443
444
|
if isinstance(req, DaemonEnvRequest):
|
|
445
|
+
from .protocol import DbPathMappingEntry
|
|
446
|
+
from .settings import get_db_path_mappings
|
|
447
|
+
|
|
444
448
|
return DaemonEnvResponse(
|
|
445
449
|
env_names=sorted(os.environ.keys()),
|
|
446
450
|
settings_env_names=settings_env_names,
|
|
451
|
+
db_path_mappings=[
|
|
452
|
+
DbPathMappingEntry(source=str(m.source), target=str(m.target))
|
|
453
|
+
for m in get_db_path_mappings()
|
|
454
|
+
],
|
|
447
455
|
)
|
|
448
456
|
|
|
449
457
|
if isinstance(req, DoctorRequest):
|
|
@@ -21,6 +21,7 @@ from .protocol import (
|
|
|
21
21
|
SearchResult,
|
|
22
22
|
)
|
|
23
23
|
from .query import query_codebase
|
|
24
|
+
from .settings import resolve_db_dir
|
|
24
25
|
from .shared import (
|
|
25
26
|
CODEBASE_DIR,
|
|
26
27
|
EMBEDDER,
|
|
@@ -170,7 +171,7 @@ class Project:
|
|
|
170
171
|
offset: int = 0,
|
|
171
172
|
) -> list[SearchResult]:
|
|
172
173
|
"""Search within this project."""
|
|
173
|
-
target_db = self._project_root / "
|
|
174
|
+
target_db = resolve_db_dir(self._project_root) / "target_sqlite.db"
|
|
174
175
|
results = await query_codebase(
|
|
175
176
|
query=query,
|
|
176
177
|
target_sqlite_db_path=target_db,
|
|
@@ -254,11 +255,14 @@ class Project:
|
|
|
254
255
|
indexer loads them fresh from disk on every run so that user edits
|
|
255
256
|
take effect without restarting the daemon.
|
|
256
257
|
"""
|
|
257
|
-
|
|
258
|
-
|
|
258
|
+
settings_dir = project_root / ".cocoindex_code"
|
|
259
|
+
settings_dir.mkdir(parents=True, exist_ok=True)
|
|
259
260
|
|
|
260
|
-
|
|
261
|
-
|
|
261
|
+
db_dir = resolve_db_dir(project_root)
|
|
262
|
+
db_dir.mkdir(parents=True, exist_ok=True)
|
|
263
|
+
|
|
264
|
+
cocoindex_db_path = db_dir / "cocoindex.db"
|
|
265
|
+
target_sqlite_db_path = db_dir / "target_sqlite.db"
|
|
262
266
|
|
|
263
267
|
settings = coco.Settings.from_env(cocoindex_db_path)
|
|
264
268
|
|
|
@@ -158,9 +158,15 @@ class DoctorResponse(_msgspec.Struct, tag="doctor"):
|
|
|
158
158
|
final: bool = False
|
|
159
159
|
|
|
160
160
|
|
|
161
|
+
class DbPathMappingEntry(_msgspec.Struct):
|
|
162
|
+
source: str
|
|
163
|
+
target: str
|
|
164
|
+
|
|
165
|
+
|
|
161
166
|
class DaemonEnvResponse(_msgspec.Struct, tag="daemon_env"):
|
|
162
167
|
env_names: list[str]
|
|
163
168
|
settings_env_names: list[str]
|
|
169
|
+
db_path_mappings: list[DbPathMappingEntry] = []
|
|
164
170
|
|
|
165
171
|
|
|
166
172
|
class ErrorResponse(_msgspec.Struct, tag="error"):
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import os
|
|
5
6
|
from dataclasses import dataclass, field
|
|
6
7
|
from pathlib import Path
|
|
7
8
|
from typing import Any
|
|
@@ -115,14 +116,89 @@ _SETTINGS_DIR_NAME = ".cocoindex_code"
|
|
|
115
116
|
_SETTINGS_FILE_NAME = "settings.yml" # project-level
|
|
116
117
|
_USER_SETTINGS_FILE_NAME = "global_settings.yml" # user-level
|
|
117
118
|
|
|
119
|
+
_ENV_DB_PATH_MAPPING = "COCOINDEX_CODE_DB_PATH_MAPPING"
|
|
120
|
+
|
|
121
|
+
|
|
122
|
+
@dataclass
|
|
123
|
+
class DbPathMapping:
|
|
124
|
+
source: Path
|
|
125
|
+
target: Path
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
_db_path_mapping: list[DbPathMapping] | None = None
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _parse_db_path_mapping() -> list[DbPathMapping]:
|
|
132
|
+
"""Parse ``COCOINDEX_CODE_DB_PATH_MAPPING`` env var.
|
|
133
|
+
|
|
134
|
+
Format: ``/src1=/dst1,/src2=/dst2``
|
|
135
|
+
Both source and target must be absolute paths.
|
|
136
|
+
"""
|
|
137
|
+
raw = os.environ.get(_ENV_DB_PATH_MAPPING, "")
|
|
138
|
+
if not raw.strip():
|
|
139
|
+
return []
|
|
140
|
+
|
|
141
|
+
mappings: list[DbPathMapping] = []
|
|
142
|
+
for entry in raw.split(","):
|
|
143
|
+
entry = entry.strip()
|
|
144
|
+
if not entry:
|
|
145
|
+
continue
|
|
146
|
+
parts = entry.split("=", 1)
|
|
147
|
+
if len(parts) != 2 or not parts[0] or not parts[1]:
|
|
148
|
+
raise ValueError(
|
|
149
|
+
f"{_ENV_DB_PATH_MAPPING}: invalid entry {entry!r}, expected format 'source=target'"
|
|
150
|
+
)
|
|
151
|
+
source = Path(parts[0])
|
|
152
|
+
target = Path(parts[1])
|
|
153
|
+
if not source.is_absolute():
|
|
154
|
+
raise ValueError(
|
|
155
|
+
f"{_ENV_DB_PATH_MAPPING}: source path must be absolute, got {source!r}"
|
|
156
|
+
)
|
|
157
|
+
if not target.is_absolute():
|
|
158
|
+
raise ValueError(
|
|
159
|
+
f"{_ENV_DB_PATH_MAPPING}: target path must be absolute, got {target!r}"
|
|
160
|
+
)
|
|
161
|
+
mappings.append(DbPathMapping(source=source.resolve(), target=target.resolve()))
|
|
162
|
+
return mappings
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def resolve_db_dir(project_root: Path) -> Path:
|
|
166
|
+
"""Return the directory for database files given a project root.
|
|
167
|
+
|
|
168
|
+
Applies ``COCOINDEX_CODE_DB_PATH_MAPPING`` if set, otherwise falls back
|
|
169
|
+
to ``project_root / ".cocoindex_code"``.
|
|
170
|
+
"""
|
|
171
|
+
global _db_path_mapping # noqa: PLW0603
|
|
172
|
+
if _db_path_mapping is None:
|
|
173
|
+
_db_path_mapping = _parse_db_path_mapping()
|
|
174
|
+
|
|
175
|
+
resolved = project_root.resolve()
|
|
176
|
+
for mapping in _db_path_mapping:
|
|
177
|
+
if resolved == mapping.source or resolved.is_relative_to(mapping.source):
|
|
178
|
+
rel = resolved.relative_to(mapping.source)
|
|
179
|
+
return mapping.target / rel
|
|
180
|
+
return project_root / _SETTINGS_DIR_NAME
|
|
181
|
+
|
|
182
|
+
|
|
183
|
+
def get_db_path_mappings() -> list[DbPathMapping]:
|
|
184
|
+
"""Return the parsed DB path mappings from ``COCOINDEX_CODE_DB_PATH_MAPPING``."""
|
|
185
|
+
global _db_path_mapping # noqa: PLW0603
|
|
186
|
+
if _db_path_mapping is None:
|
|
187
|
+
_db_path_mapping = _parse_db_path_mapping()
|
|
188
|
+
return list(_db_path_mapping)
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
def _reset_db_path_mapping_cache() -> None:
|
|
192
|
+
"""Reset the cached mapping (for tests)."""
|
|
193
|
+
global _db_path_mapping # noqa: PLW0603
|
|
194
|
+
_db_path_mapping = None
|
|
195
|
+
|
|
118
196
|
|
|
119
197
|
def user_settings_dir() -> Path:
|
|
120
198
|
"""Return ``~/.cocoindex_code/``.
|
|
121
199
|
|
|
122
200
|
Respects ``COCOINDEX_CODE_DIR`` env var for overriding the base directory.
|
|
123
201
|
"""
|
|
124
|
-
import os
|
|
125
|
-
|
|
126
202
|
override = os.environ.get("COCOINDEX_CODE_DIR")
|
|
127
203
|
if override:
|
|
128
204
|
return Path(override)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|