kodit 0.3.11__py3-none-any.whl → 0.3.13__py3-none-any.whl

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.

Potentially problematic release.


This version of kodit might be problematic. Click here for more details.

kodit/_version.py CHANGED
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '0.3.11'
21
- __version_tuple__ = version_tuple = (0, 3, 11)
20
+ __version__ = version = '0.3.13'
21
+ __version_tuple__ = version_tuple = (0, 3, 13)
kodit/app.py CHANGED
@@ -8,11 +8,12 @@ from fastapi import FastAPI, Response
8
8
  from fastapi.responses import RedirectResponse
9
9
 
10
10
  from kodit._version import version
11
+ from kodit.application.services.auto_indexing_service import AutoIndexingService
11
12
  from kodit.application.services.sync_scheduler import SyncSchedulerService
12
13
  from kodit.config import AppContext
13
14
  from kodit.infrastructure.api.v1.routers import indexes_router, search_router
14
15
  from kodit.infrastructure.api.v1.schemas.context import AppLifespanState
15
- from kodit.infrastructure.indexing.auto_indexing_service import AutoIndexingService
16
+ from kodit.log import configure_logging, configure_telemetry
16
17
  from kodit.mcp import mcp
17
18
  from kodit.middleware import ASGICancelledErrorMiddleware, logging_middleware
18
19
 
@@ -26,10 +27,13 @@ async def app_lifespan(_: FastAPI) -> AsyncIterator[AppLifespanState]:
26
27
  """Manage application lifespan for auto-indexing and sync."""
27
28
  global _auto_indexing_service, _sync_scheduler_service # noqa: PLW0603
28
29
 
30
+ # Setup app_context and implement logging and telemetry
29
31
  app_context = AppContext()
30
- db = await app_context.get_db()
32
+ configure_logging(app_context)
33
+ configure_telemetry(app_context)
31
34
 
32
35
  # Start auto-indexing service
36
+ db = await app_context.get_db()
33
37
  _auto_indexing_service = AutoIndexingService(
34
38
  app_context=app_context,
35
39
  session_factory=db.session_factory,
@@ -11,6 +11,7 @@ from kodit.application.factories.code_indexing_factory import (
11
11
  create_code_indexing_application_service,
12
12
  )
13
13
  from kodit.config import AppContext
14
+ from kodit.infrastructure.ui.progress import create_log_progress_callback
14
15
 
15
16
 
16
17
  class AutoIndexingService:
@@ -50,13 +51,20 @@ class AutoIndexingService:
50
51
 
51
52
  for source in sources:
52
53
  try:
54
+ # Only auto-index a source if it is new
55
+ if await service.does_index_exist(source):
56
+ self.log.info("Index already exists, skipping", source=source)
57
+ continue
58
+
53
59
  self.log.info("Auto-indexing source", source=source)
54
60
 
55
61
  # Create index
56
62
  index = await service.create_index_from_uri(source)
57
63
 
58
64
  # Run indexing (without progress callback for background mode)
59
- await service.run_index(index, progress_callback=None)
65
+ await service.run_index(
66
+ index, progress_callback=create_log_progress_callback()
67
+ )
60
68
 
61
69
  self.log.info("Successfully auto-indexed source", source=source)
62
70
 
@@ -53,6 +53,13 @@ class CodeIndexingApplicationService:
53
53
  self.session = session
54
54
  self.log = structlog.get_logger(__name__)
55
55
 
56
+ async def does_index_exist(self, uri: str) -> bool:
57
+ """Check if an index exists for a source."""
58
+ # Check if index already exists
59
+ sanitized_uri, _ = self.index_domain_service.sanitize_uri(uri)
60
+ existing_index = await self.index_repository.get_by_uri(sanitized_uri)
61
+ return existing_index is not None
62
+
56
63
  async def create_index_from_uri(
57
64
  self, uri: str, progress_callback: ProgressCallback | None = None
58
65
  ) -> Index:
@@ -14,6 +14,7 @@ from kodit.config import AppContext
14
14
  from kodit.domain.services.index_query_service import IndexQueryService
15
15
  from kodit.infrastructure.indexing.fusion_service import ReciprocalRankFusionService
16
16
  from kodit.infrastructure.sqlalchemy.index_repository import SqlAlchemyIndexRepository
17
+ from kodit.infrastructure.ui.progress import create_log_progress_callback
17
18
 
18
19
 
19
20
  class SyncSchedulerService:
@@ -102,7 +103,9 @@ class SyncSchedulerService:
102
103
  source=str(index.source.working_copy.remote_uri),
103
104
  )
104
105
 
105
- await service.run_index(index, progress_callback=None)
106
+ await service.run_index(
107
+ index, progress_callback=create_log_progress_callback()
108
+ )
106
109
  success_count += 1
107
110
 
108
111
  self.log.info(
kodit/config.py CHANGED
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import asyncio
6
+ from enum import Enum
6
7
  from functools import wraps
7
8
  from pathlib import Path
8
9
  from typing import TYPE_CHECKING, Annotated, Any, Literal, TypeVar
@@ -18,15 +19,22 @@ from pydantic_settings import (
18
19
  SettingsConfigDict,
19
20
  )
20
21
 
22
+ from kodit.database import Database
23
+
21
24
  if TYPE_CHECKING:
22
25
  from collections.abc import Callable, Coroutine
23
26
 
24
27
 
25
- from kodit.database import Database
28
+ class LogFormat(Enum):
29
+ """The format of the log output."""
30
+
31
+ PRETTY = "pretty"
32
+ JSON = "json"
33
+
26
34
 
27
35
  DEFAULT_BASE_DIR = Path.home() / ".kodit"
28
36
  DEFAULT_LOG_LEVEL = "INFO"
29
- DEFAULT_LOG_FORMAT = "pretty"
37
+ DEFAULT_LOG_FORMAT = LogFormat.PRETTY
30
38
  DEFAULT_DISABLE_TELEMETRY = False
31
39
  T = TypeVar("T")
32
40
 
@@ -40,6 +48,7 @@ class Endpoint(BaseModel):
40
48
  base_url: str | None = None
41
49
  model: str | None = None
42
50
  api_key: str | None = None
51
+ num_parallel_tasks: int | None = None
43
52
 
44
53
 
45
54
  class Search(BaseModel):
@@ -165,7 +174,7 @@ class AppContext(BaseSettings):
165
174
  default_factory=lambda data: f"sqlite+aiosqlite:///{data['data_dir']}/kodit.db"
166
175
  )
167
176
  log_level: str = Field(default=DEFAULT_LOG_LEVEL)
168
- log_format: str = Field(default=DEFAULT_LOG_FORMAT)
177
+ log_format: LogFormat = Field(default=DEFAULT_LOG_FORMAT)
169
178
  disable_telemetry: bool = Field(default=DEFAULT_DISABLE_TELEMETRY)
170
179
  default_endpoint: Endpoint | None = Field(
171
180
  default=None,
@@ -63,4 +63,8 @@ class IndexQueryService:
63
63
 
64
64
  async def get_snippets_by_ids(self, ids: list[int]) -> list[SnippetWithContext]:
65
65
  """Get snippets by their IDs."""
66
- return await self.index_repository.get_snippets_by_ids(ids)
66
+ snippets = await self.index_repository.get_snippets_by_ids(ids)
67
+
68
+ # Return snippets in the same order as the ids
69
+ snippets.sort(key=lambda x: ids.index(x.snippet.id or 0))
70
+ return snippets
@@ -13,6 +13,7 @@ from kodit.domain.services.enrichment_service import EnrichmentDomainService
13
13
  from kodit.domain.value_objects import (
14
14
  EnrichmentIndexRequest,
15
15
  EnrichmentRequest,
16
+ FileProcessingStatus,
16
17
  LanguageMapping,
17
18
  )
18
19
  from kodit.infrastructure.cloning.git.working_copy import GitWorkingCopyProvider
@@ -103,6 +104,11 @@ class IndexDomainService:
103
104
  files = index.source.working_copy.changed_files()
104
105
  index.delete_snippets_for_files(files)
105
106
 
107
+ # Filter out deleted files - they don't exist on disk anymore
108
+ files = [
109
+ f for f in files if f.file_processing_status != FileProcessingStatus.DELETED
110
+ ]
111
+
106
112
  # Create a set of languages to extract snippets for
107
113
  extensions = {file.extension() for file in files}
108
114
  lang_files_map: dict[str, list[domain_entities.File]] = defaultdict(list)
@@ -66,6 +66,7 @@ class LocalBM25Repository(BM25Repository):
66
66
  stemmer=self.stemmer,
67
67
  return_ids=False,
68
68
  show_progress=True,
69
+ lower=True,
69
70
  )
70
71
 
71
72
  async def index_documents(self, request: IndexRequest) -> None:
@@ -78,9 +79,8 @@ class LocalBM25Repository(BM25Repository):
78
79
  vocab = self._tokenize([doc.text for doc in request.documents])
79
80
  self._retriever().index(vocab, show_progress=False)
80
81
  self._retriever().save(self.index_path)
81
- self.snippet_ids = self.snippet_ids + [
82
- doc.snippet_id for doc in request.documents
83
- ]
82
+ # Replace snippet_ids instead of appending, since the BM25 index is rebuilt
83
+ self.snippet_ids = [doc.snippet_id for doc in request.documents]
84
84
  async with aiofiles.open(self.index_path / SNIPPET_IDS_FILE, "w") as f:
85
85
  await f.write(json.dumps(self.snippet_ids))
86
86
 
@@ -120,7 +120,7 @@ class LocalBM25Repository(BM25Repository):
120
120
 
121
121
  # Filter results by snippet_ids if provided
122
122
  filtered_results = []
123
- for result, score in zip(results[0], scores[0], strict=False):
123
+ for result, score in zip(results[0], scores[0], strict=True):
124
124
  snippet_id = int(result)
125
125
  if score > 0.0 and (
126
126
  request.snippet_ids is None or snippet_id in request.snippet_ids
@@ -70,6 +70,9 @@ UPDATE_QUERY = f"""
70
70
  UPDATE {TABLE_NAME}
71
71
  SET embedding = tokenize(passage, '{TOKENIZER_NAME}')
72
72
  """ # noqa: S608
73
+ # https://github.com/tensorchord/VectorChord-bm25:
74
+ # We intentionally make it negative so that you can use the
75
+ # default order by to get the most relevant documents first.
73
76
  SEARCH_QUERY = f"""
74
77
  SELECT
75
78
  snippet_id,
@@ -185,7 +188,7 @@ class VectorChordBM25Repository(BM25Repository):
185
188
 
186
189
  async def search(self, request: SearchRequest) -> list[SearchResult]:
187
190
  """Search documents using BM25."""
188
- if not request.query or request.query == "":
191
+ if not request.query or request.query.strip() == "":
189
192
  return []
190
193
 
191
194
  if request.snippet_ids is not None:
@@ -14,6 +14,7 @@ from kodit.infrastructure.embedding.embedding_providers.local_embedding_provider
14
14
  LocalEmbeddingProvider,
15
15
  )
16
16
  from kodit.infrastructure.embedding.embedding_providers.openai_embedding_provider import ( # noqa: E501
17
+ OPENAI_NUM_PARALLEL_TASKS,
17
18
  OpenAIEmbeddingProvider,
18
19
  )
19
20
  from kodit.infrastructure.embedding.local_vector_search_repository import (
@@ -55,6 +56,7 @@ def embedding_domain_service_factory(
55
56
  max_retries=2,
56
57
  ),
57
58
  model_name=endpoint.model or "text-embedding-3-small",
59
+ num_parallel_tasks=endpoint.num_parallel_tasks or OPENAI_NUM_PARALLEL_TASKS,
58
60
  )
59
61
  else:
60
62
  log_event("kodit.embedding", {"provider": "local"})
@@ -112,15 +112,8 @@ class LocalEmbeddingProvider(EmbeddingProvider):
112
112
 
113
113
  except Exception as e:
114
114
  self.log.exception("Error generating embeddings", error=str(e))
115
- # Return zero embeddings on error
116
- responses = [
117
- EmbeddingResponse(
118
- snippet_id=item.snippet_id,
119
- embedding=[0.0] * 1536, # Default embedding size
120
- )
121
- for item in batch
122
- ]
123
- yield responses
115
+ # Return no embeddings for this batch if there was an error
116
+ yield []
124
117
 
125
118
  def _split_sub_batches(
126
119
  self, encoding: "Encoding", data: list[EmbeddingRequest]
@@ -2,10 +2,10 @@
2
2
 
3
3
  import asyncio
4
4
  from collections.abc import AsyncGenerator
5
- from typing import Any
6
5
 
7
6
  import structlog
8
7
  import tiktoken
8
+ from openai import AsyncOpenAI
9
9
  from tiktoken import Encoding
10
10
 
11
11
  from kodit.domain.services.embedding_service import EmbeddingProvider
@@ -18,14 +18,17 @@ MAX_TOKENS = 8192 # Conservative token limit for the embedding model
18
18
  BATCH_SIZE = (
19
19
  10 # Maximum number of items per API call (keeps existing test expectations)
20
20
  )
21
- OPENAI_NUM_PARALLEL_TASKS = 25 # Semaphore limit for concurrent OpenAI requests
21
+ OPENAI_NUM_PARALLEL_TASKS = 10 # Semaphore limit for concurrent OpenAI requests
22
22
 
23
23
 
24
24
  class OpenAIEmbeddingProvider(EmbeddingProvider):
25
25
  """OpenAI embedding provider that uses OpenAI's embedding API."""
26
26
 
27
27
  def __init__(
28
- self, openai_client: Any, model_name: str = "text-embedding-3-small"
28
+ self,
29
+ openai_client: AsyncOpenAI,
30
+ model_name: str = "text-embedding-3-small",
31
+ num_parallel_tasks: int = OPENAI_NUM_PARALLEL_TASKS,
29
32
  ) -> None:
30
33
  """Initialize the OpenAI embedding provider.
31
34
 
@@ -36,6 +39,7 @@ class OpenAIEmbeddingProvider(EmbeddingProvider):
36
39
  """
37
40
  self.openai_client = openai_client
38
41
  self.model_name = model_name
42
+ self.num_parallel_tasks = num_parallel_tasks
39
43
  self.log = structlog.get_logger(__name__)
40
44
 
41
45
  # Lazily initialised token encoding
@@ -78,7 +82,7 @@ class OpenAIEmbeddingProvider(EmbeddingProvider):
78
82
  # Process batches concurrently (but bounded by a semaphore)
79
83
  # -----------------------------------------------------------------
80
84
 
81
- sem = asyncio.Semaphore(OPENAI_NUM_PARALLEL_TASKS)
85
+ sem = asyncio.Semaphore(self.num_parallel_tasks)
82
86
 
83
87
  async def _process_batch(
84
88
  batch: list[EmbeddingRequest],
@@ -99,14 +103,8 @@ class OpenAIEmbeddingProvider(EmbeddingProvider):
99
103
  ]
100
104
  except Exception as e:
101
105
  self.log.exception("Error embedding batch", error=str(e))
102
- # Fall back to zero embeddings so pipeline can continue
103
- return [
104
- EmbeddingResponse(
105
- snippet_id=item.snippet_id,
106
- embedding=[0.0] * 1536, # Default OpenAI dim
107
- )
108
- for item in batch
109
- ]
106
+ # Return no embeddings for this batch if there was an error
107
+ return []
110
108
 
111
109
  tasks = [_process_batch(batch) for batch in batched_data]
112
110
  for task in asyncio.as_completed(tasks):
@@ -9,6 +9,7 @@ from kodit.infrastructure.enrichment.local_enrichment_provider import (
9
9
  LocalEnrichmentProvider,
10
10
  )
11
11
  from kodit.infrastructure.enrichment.openai_enrichment_provider import (
12
+ OPENAI_NUM_PARALLEL_TASKS,
12
13
  OpenAIEnrichmentProvider,
13
14
  )
14
15
  from kodit.log import log_event
@@ -54,6 +55,7 @@ def enrichment_domain_service_factory(
54
55
  max_retries=2,
55
56
  ),
56
57
  model_name=endpoint.model or "gpt-4o-mini",
58
+ num_parallel_tasks=endpoint.num_parallel_tasks or OPENAI_NUM_PARALLEL_TASKS,
57
59
  )
58
60
  else:
59
61
  log_event("kodit.enrichment", {"provider": "local"})
@@ -21,7 +21,12 @@ OPENAI_NUM_PARALLEL_TASKS = 40
21
21
  class OpenAIEnrichmentProvider(EnrichmentProvider):
22
22
  """OpenAI enrichment provider implementation."""
23
23
 
24
- def __init__(self, openai_client: Any, model_name: str = "gpt-4o-mini") -> None:
24
+ def __init__(
25
+ self,
26
+ openai_client: Any,
27
+ model_name: str = "gpt-4o-mini",
28
+ num_parallel_tasks: int = OPENAI_NUM_PARALLEL_TASKS,
29
+ ) -> None:
25
30
  """Initialize the OpenAI enrichment provider.
26
31
 
27
32
  Args:
@@ -32,6 +37,7 @@ class OpenAIEnrichmentProvider(EnrichmentProvider):
32
37
  self.log = structlog.get_logger(__name__)
33
38
  self.openai_client = openai_client
34
39
  self.model_name = model_name
40
+ self.num_parallel_tasks = num_parallel_tasks
35
41
 
36
42
  async def enrich(
37
43
  self, requests: list[EnrichmentRequest]
@@ -50,7 +56,7 @@ class OpenAIEnrichmentProvider(EnrichmentProvider):
50
56
  return
51
57
 
52
58
  # Process batches in parallel with a semaphore to limit concurrent requests
53
- sem = asyncio.Semaphore(OPENAI_NUM_PARALLEL_TASKS)
59
+ sem = asyncio.Semaphore(self.num_parallel_tasks)
54
60
 
55
61
  async def process_request(request: EnrichmentRequest) -> EnrichmentResponse:
56
62
  async with sem:
@@ -2,6 +2,7 @@
2
2
 
3
3
  from collections.abc import Callable
4
4
 
5
+ import structlog
5
6
  from tqdm import tqdm # type: ignore[import-untyped]
6
7
 
7
8
  from kodit.domain.interfaces import ProgressCallback
@@ -42,6 +43,43 @@ class TQDMProgressCallback(ProgressCallback):
42
43
  # TQDM will handle cleanup with leave=False
43
44
 
44
45
 
46
+ class LogProgressCallback(ProgressCallback):
47
+ """Log-based progress callback for server environments."""
48
+
49
+ def __init__(self, milestone_interval: int = 10) -> None:
50
+ """Initialize with milestone logging interval.
51
+
52
+ Args:
53
+ milestone_interval: Percentage interval for logging (default: 10%)
54
+
55
+ """
56
+ self.milestone_interval = milestone_interval
57
+ self._last_logged_percentage = -1
58
+ self.log = structlog.get_logger()
59
+
60
+ async def on_progress(self, event: ProgressEvent) -> None:
61
+ """Log progress at milestone intervals."""
62
+ percentage = int(event.percentage)
63
+
64
+ # Log at milestone intervals (0%, 10%, 20%, etc.)
65
+ milestone = (percentage // self.milestone_interval) * self.milestone_interval
66
+
67
+ if milestone > self._last_logged_percentage and milestone <= percentage:
68
+ self.log.info(
69
+ "Progress milestone reached",
70
+ operation=event.operation,
71
+ percentage=milestone,
72
+ current=event.current,
73
+ total=event.total,
74
+ message=event.message,
75
+ )
76
+ self._last_logged_percentage = milestone
77
+
78
+ async def on_complete(self, operation: str) -> None:
79
+ """Log completion of the operation."""
80
+ self.log.info("Operation completed", operation=operation)
81
+
82
+
45
83
  class LazyProgressCallback(ProgressCallback):
46
84
  """Progress callback that only shows progress when there's actual work to do."""
47
85
 
@@ -125,3 +163,8 @@ def create_multi_stage_progress_callback() -> MultiStageProgressCallback:
125
163
  return MultiStageProgressCallback(
126
164
  lambda operation: create_progress_bar(operation, "items")
127
165
  )
166
+
167
+
168
+ def create_log_progress_callback(milestone_interval: int = 10) -> LogProgressCallback:
169
+ """Create a log-based progress callback for server environments."""
170
+ return LogProgressCallback(milestone_interval=milestone_interval)
kodit/log.py CHANGED
@@ -7,7 +7,6 @@ import shutil
7
7
  import subprocess
8
8
  import sys
9
9
  import uuid
10
- from enum import Enum
11
10
  from functools import lru_cache
12
11
  from pathlib import Path
13
12
  from typing import Any
@@ -17,7 +16,7 @@ import structlog
17
16
  from structlog.types import EventDict
18
17
 
19
18
  from kodit import _version
20
- from kodit.config import AppContext
19
+ from kodit.config import AppContext, LogFormat
21
20
 
22
21
  _MAC_RE = re.compile(r"(?:[0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}")
23
22
 
@@ -35,13 +34,6 @@ def drop_color_message_key(_, __, event_dict: EventDict) -> EventDict: # noqa:
35
34
  return event_dict
36
35
 
37
36
 
38
- class LogFormat(Enum):
39
- """The format of the log output."""
40
-
41
- PRETTY = "pretty"
42
- JSON = "json"
43
-
44
-
45
37
  def configure_logging(app_context: AppContext) -> None:
46
38
  """Configure logging for the application."""
47
39
  timestamper = structlog.processors.TimeStamper(fmt="iso")
@@ -21,6 +21,10 @@ if __name__ == "__main__":
21
21
  openapi = app.openapi()
22
22
  version = openapi.get("openapi", "unknown version")
23
23
 
24
+ # Remove any dev tags from the version by retaining only the semver part
25
+ git_tag = openapi["info"]["version"].split(".")[:3]
26
+ openapi["info"]["version"] = ".".join(git_tag)
27
+
24
28
  output_json_file = Path(args.out_dir) / "openapi.json"
25
29
 
26
30
  with output_json_file.open("w") as f:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kodit
3
- Version: 0.3.11
3
+ Version: 0.3.13
4
4
  Summary: Code indexing for better AI code generation
5
5
  Project-URL: Homepage, https://docs.helixml.tech/kodit/
6
6
  Project-URL: Documentation, https://docs.helixml.tech/kodit/
@@ -72,6 +72,8 @@ Kodit connects your AI coding assistant to external codebases to provide accurat
72
72
 
73
73
  </div>
74
74
 
75
+ :star: _Help us reach more developers and grow the Helix community. Star this repo!_
76
+
75
77
  **Helix Kodit** is an **MCP server** that connects your AI coding assistant to external codebases. It can:
76
78
 
77
79
  - Improve your AI-assisted code by providing canonical examples direct from the source
@@ -120,6 +122,19 @@ intent. Kodit has been tested to work well with:
120
122
  - **New in 0.3**: Hybrid search combining BM25 keyword search with semantic search
121
123
  - **New in 0.4**: Enhanced MCP tools with rich context parameters and metadata
122
124
 
125
+ ### Hosted MCP Server
126
+
127
+ **New in 0.4**: Try Kodit instantly with our hosted MCP server at [https://kodit.helix.ml/mcp](https://kodit.helix.ml/mcp)! No installation required - just add it to your AI coding assistant and start searching popular codebases immediately.
128
+
129
+ The hosted server provides:
130
+
131
+ - Pre-indexed popular open source repositories
132
+ - Zero configuration - works out of the box
133
+ - Same powerful search capabilities as self-hosted Kodit
134
+ - Perfect for trying Kodit before setting up your own instance
135
+
136
+ Find out more in the [hosted Kodit documentation](https://docs.helix.ml/kodit/reference/hosted-kodit/).
137
+
123
138
  ### Enterprise Ready
124
139
 
125
140
  Out of the box, Kodit works with a local SQLite database and very small, local models.
@@ -1,11 +1,11 @@
1
1
  kodit/.gitignore,sha256=ztkjgRwL9Uud1OEi36hGQeDGk3OLK1NfDEO8YqGYy8o,11
2
2
  kodit/__init__.py,sha256=aEKHYninUq1yh6jaNfvJBYg-6fenpN132nJt1UU6Jxs,59
3
- kodit/_version.py,sha256=NHYomSf4Gkc1-16-B8_7rqOM-xY3AHv8-2MTb6vZqjE,513
4
- kodit/app.py,sha256=-GY3jdRNKdTLXNoGsEtyJOGdRtxJ_t0HR_Kv24xeOdE,3862
3
+ kodit/_version.py,sha256=EwvT0-VckFIV9s9wWIrrcCCLDLz10Bn0_zRsokqxmZs,513
4
+ kodit/app.py,sha256=PZcmPNNqyBUUqXfV_pM7HpICrwZ_BjD3rBVdef9YjUs,4052
5
5
  kodit/cli.py,sha256=ZOS_VzCHGjJRZzZpaVR00QXSPIwRXPYu-pTrbEtlyR0,19328
6
- kodit/config.py,sha256=qk242V-ys2cLRq3vy6SrTi8_HFaDNL-f5i63HIpyh2s,8756
6
+ kodit/config.py,sha256=kuGdl-q5r9b7spt89-1mfVNuoQLqkXQ9-nuJFfRflUU,8940
7
7
  kodit/database.py,sha256=kI9yBm4uunsgV4-QeVoCBL0wLzU4kYmYv5qZilGnbPE,1740
8
- kodit/log.py,sha256=r0o7IpNvV-dNW-cTNWu1ouJF71vD9wHYzvqDPzeDYfw,8768
8
+ kodit/log.py,sha256=XyuseZk90gUBj1B7np2UO2EW9eE_ApayIpPRvI19KCE,8651
9
9
  kodit/mcp.py,sha256=aEcPc8dQiZaR0AswCZZNxcm_rhhUZNsEBimYti0ibSI,7221
10
10
  kodit/middleware.py,sha256=xBmC6keFeNsS0y8XUcIKzJzuefkE9bq2UhW1fR5cqxg,2770
11
11
  kodit/reporting.py,sha256=icce1ZyiADsA_Qz-mSjgn2H4SSqKuGfLKnw-yrl9nsg,2722
@@ -13,8 +13,9 @@ kodit/application/__init__.py,sha256=mH50wTpgP9dhbKztFsL8Dda9Hi18TSnMVxXtpp4aGOA
13
13
  kodit/application/factories/__init__.py,sha256=bU5CvEnaBePZ7JbkCOp1MGTNP752bnU2uEqmfy5FdRk,37
14
14
  kodit/application/factories/code_indexing_factory.py,sha256=R9f0wsj4-3NJFS5SEt_-OIGR_s_01gJXaL3PkZd8MlU,5911
15
15
  kodit/application/services/__init__.py,sha256=p5UQNw-H5sxQvs5Etfte93B3cJ1kKW6DNxK34uFvU1E,38
16
- kodit/application/services/code_indexing_application_service.py,sha256=1OA2nzsKCgD952bi9n7IygyzEymL3j7nX0yGkZaMOW0,14975
17
- kodit/application/services/sync_scheduler.py,sha256=7ZWM0ACiOrTcsW300m52fTqfWMLFmgRRZ6YUPrgUaUk,4621
16
+ kodit/application/services/auto_indexing_service.py,sha256=9eVYSHj0UHO7B5PlQtcOpnLqiNLi-f5u5d8BPb4HM5A,3154
17
+ kodit/application/services/code_indexing_application_service.py,sha256=4jlndefMecf0U235gj2PtzZmWKULK1XOd8SxE4zhZEI,15317
18
+ kodit/application/services/sync_scheduler.py,sha256=cSjlV46Xl_coq_4EYAvYesHaoOl4jvQXcQQfrZNv8mA,4767
18
19
  kodit/domain/__init__.py,sha256=TCpg4Xx-oF4mKV91lo4iXqMEfBT1OoRSYnbG-zVWolA,66
19
20
  kodit/domain/entities.py,sha256=EY43R0LOTmsaVsZGS3TWz0Bx5kF3Gm-Knqe6kLZaf9Y,8822
20
21
  kodit/domain/errors.py,sha256=yIsgCjM_yOFIg8l7l-t7jM8pgeAX4cfPq0owf7iz3DA,106
@@ -25,8 +26,8 @@ kodit/domain/services/__init__.py,sha256=Q1GhCK_PqKHYwYE4tkwDz5BIyXkJngLBBOHhzvX
25
26
  kodit/domain/services/bm25_service.py,sha256=nsfTan3XtDwXuuAu1LUv-6Jukm6qFKVqqCVymjyepZQ,3625
26
27
  kodit/domain/services/embedding_service.py,sha256=7drYRC2kjg0WJmo06a2E9N0vDnwInUlBB96twjz2BT8,4526
27
28
  kodit/domain/services/enrichment_service.py,sha256=XsXg3nV-KN4rqtC7Zro_ZiZ6RSq-1eA1MG6IDzFGyBA,1316
28
- kodit/domain/services/index_query_service.py,sha256=02UWfyB_HoHUskunGuHeq5XwQLSWxGSK4OhvxcqIfY0,2022
29
- kodit/domain/services/index_service.py,sha256=zWKnCW5L8dMJ7mG2I8knXi-vEWweF9pmY-BhbAV6i4o,11340
29
+ kodit/domain/services/index_query_service.py,sha256=cDQkgpJ3JbyeZ3z3GTIqH1JzhhKE_LBIwYE6b-lakwU,2172
30
+ kodit/domain/services/index_service.py,sha256=uVwDUEQWfZ5yJRvcjaWW7P9gCZttmnlkI51IHz52eew,11554
30
31
  kodit/infrastructure/__init__.py,sha256=HzEYIjoXnkz_i_MHO2e0sIVYweUcRnl2RpyBiTbMObU,28
31
32
  kodit/infrastructure/api/__init__.py,sha256=U0TSMPpHrlj1zbAtleuZjU3nXGwudyMe-veNBgvODwM,34
32
33
  kodit/infrastructure/api/middleware/__init__.py,sha256=6m7eE5k5buboJbuzyX5E9-Tf99yNwFaeJF0f_6HwLyM,30
@@ -42,32 +43,31 @@ kodit/infrastructure/api/v1/schemas/index.py,sha256=NtL09YtO50h-ddpAFxNf-dyxu_Xi
42
43
  kodit/infrastructure/api/v1/schemas/search.py,sha256=CWzg5SIMUJ_4yM-ZfgSLWCanMxov6AyGgQQcOMkRlGw,5618
43
44
  kodit/infrastructure/bm25/__init__.py,sha256=DmGbrEO34FOJy4e685BbyxLA7gPW1eqs2gAxsp6JOuM,34
44
45
  kodit/infrastructure/bm25/bm25_factory.py,sha256=I4eo7qRslnyXIRkBf-StZ5ga2Evrr5J5YFocTChFD3g,884
45
- kodit/infrastructure/bm25/local_bm25_repository.py,sha256=rDx8orGhg38n0zSpybEt5QLOWHY2Yt5IxIf9UtlhXXU,4629
46
- kodit/infrastructure/bm25/vectorchord_bm25_repository.py,sha256=Jyic55V-38XeTad462Ge751iKyc0X8RNVBM9pr_DVJk,7439
46
+ kodit/infrastructure/bm25/local_bm25_repository.py,sha256=qdDRiiap168XivjkukRHVj1fxlprqRIG0iRSaseLv5I,4695
47
+ kodit/infrastructure/bm25/vectorchord_bm25_repository.py,sha256=p6ht5K-jlDTvEkmoQygmyLLo9yCn_UFx5MtNTmTImjI,7619
47
48
  kodit/infrastructure/cloning/__init__.py,sha256=IzIvX-yeRRFZ-lfvPVSEe_qXszO6DGQdjKwwDigexyQ,30
48
49
  kodit/infrastructure/cloning/metadata.py,sha256=GD2UnCC1oR82RD0SVUqk9CJOqzXPxhOAHVOp7jqN6Qc,3571
49
50
  kodit/infrastructure/cloning/git/__init__.py,sha256=20ePcp0qE6BuLsjsv4KYB1DzKhMIMsPXwEqIEZtjTJs,34
50
51
  kodit/infrastructure/cloning/git/working_copy.py,sha256=qYcrR5qP1rhWZiYGMT1p-1Alavi_YvQLXx4MgIV7eXs,2611
51
52
  kodit/infrastructure/embedding/__init__.py,sha256=F-8nLlWAerYJ0MOIA4tbXHLan8bW5rRR84vzxx6tRKI,39
52
- kodit/infrastructure/embedding/embedding_factory.py,sha256=SOVX3wGxW8Qo2lJmMZ0kRssXKn6A4W7DmSpgo0zWTfM,3625
53
+ kodit/infrastructure/embedding/embedding_factory.py,sha256=BsePuOAU4UmFP1hbn3WwZkY6dTG-oxlte0l7P_LsuuA,3745
53
54
  kodit/infrastructure/embedding/local_vector_search_repository.py,sha256=ExweyNEL5cP-g3eDhGqZSih7zhdOrop2WdFPPJL-tB4,3505
54
55
  kodit/infrastructure/embedding/vectorchord_vector_search_repository.py,sha256=PIoU0HsDlaoXDXnGjOR0LAkAcW4JiE3ymJy_SBhEopc,8030
55
56
  kodit/infrastructure/embedding/embedding_providers/__init__.py,sha256=qeZ-oAIAxMl5QqebGtO1lq-tHjl_ucAwOXePklcwwGk,34
56
57
  kodit/infrastructure/embedding/embedding_providers/batching.py,sha256=a8CL9PX2VLmbeg616fc_lQzfC4BWTVn32m4SEhXpHxc,3279
57
58
  kodit/infrastructure/embedding/embedding_providers/hash_embedding_provider.py,sha256=V6OdCuWyQQOvo3OJGRi-gBKDApIcrELydFg7T696P5s,2257
58
- kodit/infrastructure/embedding/embedding_providers/local_embedding_provider.py,sha256=U5fc8jUP8wF-nq1zo-CfSbJbLQyE-3muKmRCaYGtytk,4387
59
- kodit/infrastructure/embedding/embedding_providers/openai_embedding_provider.py,sha256=LIK9Iir7geraZoqiaNbeHv3hXrghZRDpYGJDEjZaqzQ,4086
59
+ kodit/infrastructure/embedding/embedding_providers/local_embedding_provider.py,sha256=9aLV1Zg4KMhYWlGRwgAUtswW4aIabNqbsipWhAn64RI,4133
60
+ kodit/infrastructure/embedding/embedding_providers/openai_embedding_provider.py,sha256=QfvdXXbWa-1DQriCzV-TmFm3XGqnVP_7PSQ6u6fKnuw,3973
60
61
  kodit/infrastructure/enrichment/__init__.py,sha256=8acZKNzql8Fs0lceFu9U3KoUrOptRBtVIxr_Iw6lz3Y,40
61
- kodit/infrastructure/enrichment/enrichment_factory.py,sha256=2h-c96FWgSi0UG6IeL9Yjae80KYdzJqes5HIJQrkpc8,1919
62
+ kodit/infrastructure/enrichment/enrichment_factory.py,sha256=_JWkna3g8q8hzaPq1NRfZU9Y_sv99xcloM4BCJAWmHw,2039
62
63
  kodit/infrastructure/enrichment/local_enrichment_provider.py,sha256=7Vlwu1jPJ5KNUn1a51M1P-laUd5YVFJA8EeH6KO-95k,3960
63
64
  kodit/infrastructure/enrichment/null_enrichment_provider.py,sha256=DhZkJBnkvXg_XSAs-oKiFnKqYFPnmTl3ikdxrqeEfbc,713
64
- kodit/infrastructure/enrichment/openai_enrichment_provider.py,sha256=fenq4HiJ2UkrzsE2D0A0qpmro38z9mKaIzKKU5v7hnY,3189
65
+ kodit/infrastructure/enrichment/openai_enrichment_provider.py,sha256=quu9GLGhxGk3ilrg5kPZdGiCTfuQ20JuwM3Grv6qaQE,3332
65
66
  kodit/infrastructure/git/__init__.py,sha256=0iMosFzudj4_xNIMe2SRbV6l5bWqkjnUsZoFsoZFuM8,33
66
67
  kodit/infrastructure/git/git_utils.py,sha256=KERwmhWDR4ooMQKS-nSPxjvdCzoWF9NS6nhdeXyzdtY,571
67
68
  kodit/infrastructure/ignore/__init__.py,sha256=VzFv8XOzHmsu0MEGnWVSF6KsgqLBmvHlRqAkT1Xb1MY,36
68
69
  kodit/infrastructure/ignore/ignore_pattern_provider.py,sha256=zdxun3GodLfXxyssBK8QDUK58xb4fBJ0SKcHUyn3pzM,2131
69
70
  kodit/infrastructure/indexing/__init__.py,sha256=7UPRa2jwCAsa0Orsp6PqXSF8iIXJVzXHMFmrKkI9yH8,38
70
- kodit/infrastructure/indexing/auto_indexing_service.py,sha256=PgAyrmR8jNkAOlGnhQjFkqoE22oh-IwYTCg_v4o45Fo,2764
71
71
  kodit/infrastructure/indexing/fusion_service.py,sha256=2B0guBsuKz19uWcs18sIJpUJPzXoRvULgl7UNWQGysA,1809
72
72
  kodit/infrastructure/mappers/__init__.py,sha256=QPHOjNreXmBPPovZ6elnYFS0vD-IsmrGl4TT01FCKro,77
73
73
  kodit/infrastructure/mappers/index_mapper.py,sha256=ZSfu8kjTaa8_UY0nTqr4b02NS3VrjqZYkduCN71AL2g,12743
@@ -79,7 +79,7 @@ kodit/infrastructure/sqlalchemy/embedding_repository.py,sha256=dC2Wzj_zQiWExwfSc
79
79
  kodit/infrastructure/sqlalchemy/entities.py,sha256=Dmh0z-dMI0wfMAPpf62kxU4md6NUH9P5Nx1QSTITOfg,5961
80
80
  kodit/infrastructure/sqlalchemy/index_repository.py,sha256=UlDH6Qluuat1T0GaATko29fwQPAaUh2WLWiGurBW42w,23598
81
81
  kodit/infrastructure/ui/__init__.py,sha256=CzbLOBwIZ6B6iAHEd1L8cIBydCj-n_kobxJAhz2I9_Y,32
82
- kodit/infrastructure/ui/progress.py,sha256=LmEAQKWWSspqb0fOwruyxBfzBG7gmHd6z1iBco1d7_4,4823
82
+ kodit/infrastructure/ui/progress.py,sha256=SHEUoQA_x36z4nqHrQduVrrWIvFfX6QxAawC7zQ50pw,6433
83
83
  kodit/infrastructure/ui/spinner.py,sha256=GcP115qtR0VEnGfMEtsGoAUpRzVGUSfiUXfoJJERngA,2357
84
84
  kodit/migrations/README,sha256=ISVtAOvqvKk_5ThM5ioJE-lMkvf9IbknFUFVU_vPma4,58
85
85
  kodit/migrations/__init__.py,sha256=lP5MuwlyWRMO6UcDWnQcQ3G-GYHcFb6rl9gYPHJ1sjo,40
@@ -93,10 +93,10 @@ kodit/migrations/versions/9e53ea8bb3b0_add_authors.py,sha256=a32Zm8KUQyiiLkjKNPY
93
93
  kodit/migrations/versions/__init__.py,sha256=9-lHzptItTzq_fomdIRBegQNm4Znx6pVjwD4MiqRIdo,36
94
94
  kodit/migrations/versions/c3f5137d30f5_index_all_the_things.py,sha256=r7ukmJ_axXLAWewYx-F1fEmZ4JbtFd37i7cSb0tq3y0,1722
95
95
  kodit/utils/__init__.py,sha256=DPEB1i8evnLF4Ns3huuAYg-0pKBFKUFuiDzOKG9r-sw,33
96
- kodit/utils/dump_openapi.py,sha256=_1wIrJLA-RlvgZ_8tMzDF0Kdee6UaPp_9DQjfHoM-xc,1062
96
+ kodit/utils/dump_openapi.py,sha256=29VdjHpNSaGAg7RjQw0meq1OLhljCx1ElgBlTC8xoF4,1247
97
97
  kodit/utils/path_utils.py,sha256=thK6YGGNvQThdBaCYCCeCvS1L8x-lwl3AoGht2jnjGw,1645
98
- kodit-0.3.11.dist-info/METADATA,sha256=B06xZGWPvpr5EXz_4GjzeYKeOk6J7lFQg6o2zkgLGgc,6974
99
- kodit-0.3.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
100
- kodit-0.3.11.dist-info/entry_points.txt,sha256=hoTn-1aKyTItjnY91fnO-rV5uaWQLQ-Vi7V5et2IbHY,40
101
- kodit-0.3.11.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
102
- kodit-0.3.11.dist-info/RECORD,,
98
+ kodit-0.3.13.dist-info/METADATA,sha256=L8ME2qCp94fPYIbnQ7c4yaPyfEm2J-bOVNKfg6bknGw,7672
99
+ kodit-0.3.13.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
100
+ kodit-0.3.13.dist-info/entry_points.txt,sha256=hoTn-1aKyTItjnY91fnO-rV5uaWQLQ-Vi7V5et2IbHY,40
101
+ kodit-0.3.13.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
102
+ kodit-0.3.13.dist-info/RECORD,,
File without changes