kodit 0.1.14__py3-none-any.whl → 0.1.15__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.

Files changed (33) hide show
  1. kodit/_version.py +2 -2
  2. kodit/bm25/keyword_search_factory.py +17 -0
  3. kodit/bm25/keyword_search_service.py +34 -0
  4. kodit/bm25/{bm25.py → local_bm25.py} +40 -14
  5. kodit/bm25/vectorchord_bm25.py +193 -0
  6. kodit/cli.py +14 -11
  7. kodit/config.py +9 -2
  8. kodit/database.py +4 -2
  9. kodit/embedding/embedding_factory.py +44 -0
  10. kodit/embedding/embedding_provider/__init__.py +1 -0
  11. kodit/embedding/embedding_provider/embedding_provider.py +53 -0
  12. kodit/embedding/embedding_provider/hash_embedding_provider.py +77 -0
  13. kodit/embedding/embedding_provider/local_embedding_provider.py +58 -0
  14. kodit/embedding/embedding_provider/openai_embedding_provider.py +63 -0
  15. kodit/embedding/embedding_repository.py +206 -0
  16. kodit/embedding/local_vector_search_service.py +50 -0
  17. kodit/embedding/vector_search_service.py +38 -0
  18. kodit/embedding/vectorchord_vector_search_service.py +145 -0
  19. kodit/indexing/indexing_repository.py +24 -4
  20. kodit/indexing/indexing_service.py +25 -30
  21. kodit/mcp.py +7 -3
  22. kodit/search/search_repository.py +0 -121
  23. kodit/search/search_service.py +12 -24
  24. kodit/source/source_service.py +9 -3
  25. kodit/util/__init__.py +1 -0
  26. kodit/util/spinner.py +59 -0
  27. {kodit-0.1.14.dist-info → kodit-0.1.15.dist-info}/METADATA +2 -1
  28. kodit-0.1.15.dist-info/RECORD +58 -0
  29. kodit/embedding/embedding.py +0 -203
  30. kodit-0.1.14.dist-info/RECORD +0 -44
  31. {kodit-0.1.14.dist-info → kodit-0.1.15.dist-info}/WHEEL +0 -0
  32. {kodit-0.1.14.dist-info → kodit-0.1.15.dist-info}/entry_points.txt +0 -0
  33. {kodit-0.1.14.dist-info → kodit-0.1.15.dist-info}/licenses/LICENSE +0 -0
@@ -13,13 +13,16 @@ import pydantic
13
13
  import structlog
14
14
  from tqdm.asyncio import tqdm
15
15
 
16
- from kodit.bm25.bm25 import BM25Service
17
- from kodit.embedding.embedding import Embedder, EmbeddingInput
18
- from kodit.embedding.embedding_models import Embedding, EmbeddingType
16
+ from kodit.bm25.keyword_search_service import BM25Document, KeywordSearchProvider
17
+ from kodit.embedding.vector_search_service import (
18
+ VectorSearchRequest,
19
+ VectorSearchService,
20
+ )
19
21
  from kodit.indexing.indexing_models import Snippet
20
22
  from kodit.indexing.indexing_repository import IndexRepository
21
23
  from kodit.snippets.snippets import SnippetService
22
24
  from kodit.source.source_service import SourceService
25
+ from kodit.util.spinner import Spinner
23
26
 
24
27
  # List of MIME types that are blacklisted from being indexed
25
28
  MIME_BLACKLIST = ["unknown/unknown"]
@@ -51,8 +54,8 @@ class IndexService:
51
54
  self,
52
55
  repository: IndexRepository,
53
56
  source_service: SourceService,
54
- data_dir: Path,
55
- embedding_service: Embedder,
57
+ keyword_search_provider: KeywordSearchProvider,
58
+ vector_search_service: VectorSearchService,
56
59
  ) -> None:
57
60
  """Initialize the index service.
58
61
 
@@ -65,8 +68,8 @@ class IndexService:
65
68
  self.source_service = source_service
66
69
  self.snippet_service = SnippetService()
67
70
  self.log = structlog.get_logger(__name__)
68
- self.bm25 = BM25Service(data_dir)
69
- self.code_embedding_service = embedding_service
71
+ self.keyword_search_provider = keyword_search_provider
72
+ self.code_search_service = vector_search_service
70
73
 
71
74
  async def create(self, source_id: int) -> IndexView:
72
75
  """Create a new index for a source.
@@ -126,36 +129,27 @@ class IndexService:
126
129
  msg = f"Index not found: {index_id}"
127
130
  raise ValueError(msg)
128
131
 
129
- # First delete all old snippets, if they exist
130
- await self.repository.delete_all_snippets(index_id)
131
-
132
132
  # Create snippets for supported file types
133
133
  await self._create_snippets(index_id)
134
134
 
135
135
  snippets = await self.repository.get_all_snippets(index_id)
136
136
 
137
137
  self.log.info("Creating keyword index")
138
- self.bm25.index(
139
- [
140
- snippet.content
141
- for snippet in tqdm(snippets, total=len(snippets), leave=False)
142
- ]
143
- )
138
+ with Spinner():
139
+ await self.keyword_search_provider.index(
140
+ [
141
+ BM25Document(snippet_id=snippet.id, text=snippet.content)
142
+ for snippet in snippets
143
+ ]
144
+ )
144
145
 
145
146
  self.log.info("Creating semantic code index")
146
- async for e in tqdm(
147
- self.code_embedding_service.embed(
148
- [EmbeddingInput(snippet.id, snippet.content) for snippet in snippets]
149
- ),
150
- total=len(snippets),
151
- leave=False,
152
- ):
153
- await self.repository.add_embedding(
154
- Embedding(
155
- snippet_id=e.id,
156
- embedding=e.embedding,
157
- type=EmbeddingType.CODE,
158
- )
147
+ with Spinner():
148
+ await self.code_search_service.index(
149
+ [
150
+ VectorSearchRequest(snippet.id, snippet.content)
151
+ for snippet in snippets
152
+ ]
159
153
  )
160
154
 
161
155
  # Update index timestamp
@@ -174,6 +168,7 @@ class IndexService:
174
168
 
175
169
  """
176
170
  files = await self.repository.files_for_index(index_id)
171
+ self.log.info("Creating snippets for files", index_id=index_id)
177
172
  for file in tqdm(files, total=len(files), leave=False):
178
173
  # Skip unsupported file types
179
174
  if file.mime_type in MIME_BLACKLIST:
@@ -195,4 +190,4 @@ class IndexService:
195
190
  file_id=file.id,
196
191
  content=snippet.text,
197
192
  )
198
- await self.repository.add_snippet(s)
193
+ await self.repository.add_snippet_or_update_content(s)
kodit/mcp.py CHANGED
@@ -12,9 +12,10 @@ from pydantic import Field
12
12
  from sqlalchemy.ext.asyncio import AsyncSession
13
13
 
14
14
  from kodit._version import version
15
+ from kodit.bm25.keyword_search_factory import keyword_search_factory
15
16
  from kodit.config import AppContext
16
17
  from kodit.database import Database
17
- from kodit.embedding.embedding import embedding_factory
18
+ from kodit.embedding.embedding_factory import embedding_factory
18
19
  from kodit.search.search_repository import SearchRepository
19
20
  from kodit.search.search_service import SearchRequest, SearchResult, SearchService
20
21
 
@@ -129,13 +130,16 @@ async def search(
129
130
 
130
131
  log.debug("Creating embedding service")
131
132
  embedding_service = embedding_factory(
132
- mcp_context.app_context.get_default_openai_client()
133
+ app_context=mcp_context.app_context, session=mcp_context.session
133
134
  )
134
135
 
135
136
  log.debug("Creating search service")
136
137
  search_service = SearchService(
137
138
  repository=search_repository,
138
- data_dir=mcp_context.app_context.get_data_dir(),
139
+ keyword_search_provider=keyword_search_factory(
140
+ app_context=mcp_context.app_context,
141
+ session=mcp_context.session,
142
+ ),
139
143
  embedding_service=embedding_service,
140
144
  )
141
145
 
@@ -2,13 +2,11 @@
2
2
 
3
3
  from typing import TypeVar
4
4
 
5
- import numpy as np
6
5
  from sqlalchemy import (
7
6
  select,
8
7
  )
9
8
  from sqlalchemy.ext.asyncio import AsyncSession
10
9
 
11
- from kodit.embedding.embedding_models import Embedding, EmbeddingType
12
10
  from kodit.indexing.indexing_models import Snippet
13
11
  from kodit.source.source_models import File
14
12
 
@@ -57,122 +55,3 @@ class SearchRepository:
57
55
 
58
56
  # Return results in the same order as input IDs
59
57
  return [id_to_result[i] for i in ids]
60
-
61
- async def list_semantic_results(
62
- self, embedding_type: EmbeddingType, embedding: list[float], top_k: int = 10
63
- ) -> list[tuple[int, float]]:
64
- """List semantic results using cosine similarity.
65
-
66
- This implementation fetches all embeddings of the given type and computes
67
- cosine similarity in Python using NumPy for better performance.
68
-
69
- Args:
70
- embedding_type: The type of embeddings to search
71
- embedding: The query embedding vector
72
- top_k: Number of results to return
73
-
74
- Returns:
75
- List of (snippet_id, similarity_score) tuples, sorted by similarity
76
-
77
- """
78
- # Step 1: Fetch embeddings from database
79
- embeddings = await self._list_embedding_values(embedding_type)
80
- if not embeddings:
81
- return []
82
-
83
- # Step 2: Convert to numpy arrays
84
- stored_vecs, query_vec = self._prepare_vectors(embeddings, embedding)
85
-
86
- # Step 3: Compute similarities
87
- similarities = self._compute_similarities(stored_vecs, query_vec)
88
-
89
- # Step 4: Get top-k results
90
- return self._get_top_k_results(similarities, embeddings, top_k)
91
-
92
- async def _list_embedding_values(
93
- self, embedding_type: EmbeddingType
94
- ) -> list[tuple[int, list[float]]]:
95
- """List all embeddings of a given type from the database.
96
-
97
- Args:
98
- embedding_type: The type of embeddings to fetch
99
-
100
- Returns:
101
- List of (snippet_id, embedding) tuples
102
-
103
- """
104
- # Only select the fields we need and use a more efficient query
105
- query = select(Embedding.snippet_id, Embedding.embedding).where(
106
- Embedding.type == embedding_type
107
- )
108
- rows = await self.session.execute(query)
109
- return [tuple(row) for row in rows.all()] # Convert Row objects to tuples
110
-
111
- def _prepare_vectors(
112
- self, embeddings: list[tuple[int, list[float]]], query_embedding: list[float]
113
- ) -> tuple[np.ndarray, np.ndarray]:
114
- """Convert embeddings to numpy arrays.
115
-
116
- Args:
117
- embeddings: List of (snippet_id, embedding) tuples
118
- query_embedding: Query embedding vector
119
-
120
- Returns:
121
- Tuple of (stored_vectors, query_vector) as numpy arrays
122
-
123
- """
124
- try:
125
- stored_vecs = np.array(
126
- [emb[1] for emb in embeddings]
127
- ) # Use index 1 to get embedding
128
- except ValueError as e:
129
- if "inhomogeneous" in str(e):
130
- msg = (
131
- "The database has returned embeddings of different sizes. If you"
132
- "have recently updated the embedding model, you will need to"
133
- "delete your database and re-index your snippets."
134
- )
135
- raise ValueError(msg) from e
136
- raise
137
-
138
- query_vec = np.array(query_embedding)
139
- return stored_vecs, query_vec
140
-
141
- def _compute_similarities(
142
- self, stored_vecs: np.ndarray, query_vec: np.ndarray
143
- ) -> np.ndarray:
144
- """Compute cosine similarities between stored vectors and query vector.
145
-
146
- Args:
147
- stored_vecs: Array of stored embedding vectors
148
- query_vec: Query embedding vector
149
-
150
- Returns:
151
- Array of similarity scores
152
-
153
- """
154
- stored_norms = np.linalg.norm(stored_vecs, axis=1)
155
- query_norm = np.linalg.norm(query_vec)
156
- return np.dot(stored_vecs, query_vec) / (stored_norms * query_norm)
157
-
158
- def _get_top_k_results(
159
- self,
160
- similarities: np.ndarray,
161
- embeddings: list[tuple[int, list[float]]],
162
- top_k: int,
163
- ) -> list[tuple[int, float]]:
164
- """Get top-k results by similarity score.
165
-
166
- Args:
167
- similarities: Array of similarity scores
168
- embeddings: List of (snippet_id, embedding) tuples
169
- top_k: Number of results to return
170
-
171
- Returns:
172
- List of (snippet_id, similarity_score) tuples
173
-
174
- """
175
- top_indices = np.argsort(similarities)[::-1][:top_k]
176
- return [
177
- (embeddings[i][0], float(similarities[i])) for i in top_indices
178
- ] # Use index 0 to get snippet_id
@@ -1,13 +1,10 @@
1
1
  """Search service."""
2
2
 
3
- from pathlib import Path
4
-
5
3
  import pydantic
6
4
  import structlog
7
5
 
8
- from kodit.bm25.bm25 import BM25Service
9
- from kodit.embedding.embedding import Embedder
10
- from kodit.embedding.embedding_models import EmbeddingType
6
+ from kodit.bm25.keyword_search_service import BM25Result, KeywordSearchProvider
7
+ from kodit.embedding.vector_search_service import VectorSearchService
11
8
  from kodit.search.search_repository import SearchRepository
12
9
 
13
10
 
@@ -44,25 +41,25 @@ class SearchService:
44
41
  def __init__(
45
42
  self,
46
43
  repository: SearchRepository,
47
- data_dir: Path,
48
- embedding_service: Embedder,
44
+ keyword_search_provider: KeywordSearchProvider,
45
+ embedding_service: VectorSearchService,
49
46
  ) -> None:
50
47
  """Initialize the search service."""
51
48
  self.repository = repository
52
49
  self.log = structlog.get_logger(__name__)
53
- self.bm25 = BM25Service(data_dir)
50
+ self.keyword_search_provider = keyword_search_provider
54
51
  self.code_embedding_service = embedding_service
55
52
 
56
53
  async def search(self, request: SearchRequest) -> list[SearchResult]:
57
54
  """Search for relevant data."""
58
55
  fusion_list = []
59
56
  if request.keywords:
60
- snippet_ids = await self.repository.list_snippet_ids()
61
-
62
57
  # Gather results for each keyword
63
- result_ids: list[tuple[int, float]] = []
58
+ result_ids: list[BM25Result] = []
64
59
  for keyword in request.keywords:
65
- results = self.bm25.retrieve(snippet_ids, keyword, request.top_k)
60
+ results = await self.keyword_search_provider.retrieve(
61
+ keyword, request.top_k
62
+ )
66
63
  result_ids.extend(results)
67
64
 
68
65
  # Sort results by score
@@ -76,19 +73,10 @@ class SearchService:
76
73
  # Compute embedding for semantic query
77
74
  semantic_results = []
78
75
  if request.code_query:
79
- query_embedding = await anext(
80
- self.code_embedding_service.query([request.code_query])
81
- )
82
-
83
- query_results = await self.repository.list_semantic_results(
84
- EmbeddingType.CODE, query_embedding, top_k=request.top_k
76
+ query_embedding = await self.code_embedding_service.retrieve(
77
+ request.code_query, top_k=request.top_k
85
78
  )
86
-
87
- # Sort results by score
88
- query_results.sort(key=lambda x: x[1], reverse=True)
89
-
90
- # Extract the snippet ids from the query results
91
- semantic_results = [x[0] for x in query_results]
79
+ semantic_results = [x.snippet_id for x in query_embedding]
92
80
  fusion_list.append(semantic_results)
93
81
 
94
82
  if len(fusion_list) == 0:
@@ -109,6 +109,8 @@ class SourceService:
109
109
  uri_or_path_like = uri_or_path_like + ".git"
110
110
  try:
111
111
  return await self._create_git_source(uri_or_path_like)
112
+ except git.GitCommandError:
113
+ raise
112
114
  except ValueError:
113
115
  pass
114
116
 
@@ -197,11 +199,14 @@ class SourceService:
197
199
  clone_path.mkdir(parents=True, exist_ok=True)
198
200
 
199
201
  try:
200
- # Clone the repository
202
+ self.log.info("Cloning repository", uri=uri, clone_path=str(clone_path))
201
203
  git.Repo.clone_from(uri, clone_path)
202
204
  except git.GitCommandError as e:
203
- msg = f"Failed to clone repository: {e}"
204
- raise ValueError(msg) from e
205
+ if "already exists and is not an empty directory" in str(e):
206
+ self.log.info("Repository already exists, reusing...", uri=uri)
207
+ else:
208
+ msg = f"Failed to clone repository: {e}"
209
+ raise ValueError(msg) from e
205
210
 
206
211
  source = await self.repository.create_source(
207
212
  Source(uri=uri, cloned_path=str(clone_path)),
@@ -212,6 +217,7 @@ class SourceService:
212
217
  file_count = sum(1 for _ in clone_path.rglob("*") if _.is_file())
213
218
 
214
219
  # Process each file in the source directory
220
+ self.log.info("Inspecting files", source_id=source.id)
215
221
  for path in tqdm(clone_path.rglob("*"), total=file_count, leave=False):
216
222
  await self._process_file(source.id, path.absolute())
217
223
 
kodit/util/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """Utility functions and classes."""
kodit/util/spinner.py ADDED
@@ -0,0 +1,59 @@
1
+ """Spinner for long-running tasks."""
2
+
3
+ import itertools
4
+ import sys
5
+ import threading
6
+ import time
7
+
8
+
9
+ class Spinner:
10
+ """Spinner for long-running tasks."""
11
+
12
+ def __init__(self, delay: float = 0.1) -> None:
13
+ """Initialize the spinner."""
14
+ self.spinner = itertools.cycle(["-", "/", "|", "\\"])
15
+ self.delay = delay
16
+ self.busy = False
17
+ self.spinner_visible = False
18
+
19
+ def write_next(self) -> None:
20
+ """Write the next character of the spinner."""
21
+ with self._screen_lock:
22
+ if not self.spinner_visible:
23
+ sys.stdout.write(next(self.spinner))
24
+ self.spinner_visible = True
25
+ sys.stdout.flush()
26
+
27
+ def remove_spinner(self, cleanup: bool = False) -> None: # noqa: FBT001, FBT002
28
+ """Remove the spinner."""
29
+ with self._screen_lock:
30
+ if self.spinner_visible:
31
+ sys.stdout.write("\b")
32
+ self.spinner_visible = False
33
+ if cleanup:
34
+ sys.stdout.write(" ") # overwrite spinner with blank
35
+ sys.stdout.write("\r") # move to next line
36
+ sys.stdout.flush()
37
+
38
+ def spinner_task(self) -> None:
39
+ """Task that runs the spinner."""
40
+ while self.busy:
41
+ self.write_next()
42
+ time.sleep(self.delay)
43
+ self.remove_spinner()
44
+
45
+ def __enter__(self) -> None:
46
+ """Enter the context manager."""
47
+ if sys.stdout.isatty():
48
+ self._screen_lock = threading.Lock()
49
+ self.busy = True
50
+ self.thread = threading.Thread(target=self.spinner_task)
51
+ self.thread.start()
52
+
53
+ def __exit__(self, exception: object, value: object, tb: object) -> None:
54
+ """Exit the context manager."""
55
+ if sys.stdout.isatty():
56
+ self.busy = False
57
+ self.remove_spinner(cleanup=True)
58
+ else:
59
+ sys.stdout.write("\r")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: kodit
3
- Version: 0.1.14
3
+ Version: 0.1.15
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/
@@ -21,6 +21,7 @@ Requires-Dist: aiofiles>=24.1.0
21
21
  Requires-Dist: aiosqlite>=0.20.0
22
22
  Requires-Dist: alembic>=1.15.2
23
23
  Requires-Dist: asgi-correlation-id>=4.3.4
24
+ Requires-Dist: asyncpg>=0.30.0
24
25
  Requires-Dist: better-exceptions>=0.3.3
25
26
  Requires-Dist: bm25s[core]>=0.2.12
26
27
  Requires-Dist: click>=8.1.8
@@ -0,0 +1,58 @@
1
+ kodit/.gitignore,sha256=ztkjgRwL9Uud1OEi36hGQeDGk3OLK1NfDEO8YqGYy8o,11
2
+ kodit/__init__.py,sha256=aEKHYninUq1yh6jaNfvJBYg-6fenpN132nJt1UU6Jxs,59
3
+ kodit/_version.py,sha256=OX-WIjJlMaFvqRmCfLtOYEOYoiov9NdOA089N36rG-g,513
4
+ kodit/app.py,sha256=Mr5BFHOHx5zppwjC4XPWVvHjwgl1yrKbUjTWXKubJQM,891
5
+ kodit/cli.py,sha256=wAaMZQs-h6hyashWB3DBR2GIf496vfHmepcXhpa7-eM,8085
6
+ kodit/config.py,sha256=2W2u5J8j-Mbt-C4xzOuK-PeuDCx0S_rnCXPhBwvfLT4,4353
7
+ kodit/database.py,sha256=WB1KpVxUYPgiJGU0gJa2hqytYB8wJEJ5z3WayhWzNMU,2403
8
+ kodit/log.py,sha256=HU1OmuxO4FcVw61k4WW7Y4WM7BrDaeplw1PcBHhuIZY,5434
9
+ kodit/mcp.py,sha256=HA3R7YG0Al1A6MjSCSIi0hEGXG3WP7tix-N5AROasCM,5278
10
+ kodit/middleware.py,sha256=I6FOkqG9-8RH5kR1-0ZoQWfE4qLCB8lZYv8H_OCH29o,2714
11
+ kodit/bm25/__init__.py,sha256=j8zyriNWhbwE5Lbybzg1hQAhANlU9mKHWw4beeUR6og,19
12
+ kodit/bm25/keyword_search_factory.py,sha256=rp-wx3DJsc2KlELK1V337EyeYvmwnMQwUqOo1WVPSmg,631
13
+ kodit/bm25/keyword_search_service.py,sha256=aBbWQKgQmi2re3EIHdXFS00n7Wj3b2D0pZsLZ4qmHfE,754
14
+ kodit/bm25/local_bm25.py,sha256=AAbFhbQDqyL3d7jsPL7W4HsLxdoYctaDsREUXOLy6jM,3260
15
+ kodit/bm25/vectorchord_bm25.py,sha256=_nGrkUReYLLV-L8RIuIVLwjuhSYZl9T532n5OVf0kWs,6393
16
+ kodit/embedding/__init__.py,sha256=h9NXzDA1r-K23nvBajBV-RJzHJN0p3UJ7UQsmdnOoRw,24
17
+ kodit/embedding/embedding_factory.py,sha256=qzoxBS3scR-ABd-u9215uGES7c6clYy2DiKcSDQivnA,1603
18
+ kodit/embedding/embedding_models.py,sha256=rN90vSs86dYiqoawcp8E9jtwY31JoJXYfaDlsJK7uqc,656
19
+ kodit/embedding/embedding_repository.py,sha256=-ux3scpBzel8c0pMH9fNOEsSXFIzl-IfgaWrkTb1szo,6907
20
+ kodit/embedding/local_vector_search_service.py,sha256=hkF0qlfzjyGt400qIX9Mr6B7b7i8WvYIYWN2Z2C_pcs,1907
21
+ kodit/embedding/vector_search_service.py,sha256=pQJ129QjGrAWOXzqkywmgtDRpy8_gtzYgkivyqF9Vrs,1009
22
+ kodit/embedding/vectorchord_vector_search_service.py,sha256=OsVeM3gpoT8Ihzh-kEIzBm3xh_a4D-sErPvsQSKCME8,4732
23
+ kodit/embedding/embedding_provider/__init__.py,sha256=h9NXzDA1r-K23nvBajBV-RJzHJN0p3UJ7UQsmdnOoRw,24
24
+ kodit/embedding/embedding_provider/embedding_provider.py,sha256=NKs4nriup47R8xRciP07NE1-eZE9RPHklS7VH910UZ4,1537
25
+ kodit/embedding/embedding_provider/hash_embedding_provider.py,sha256=nAhlhh8j8PqqCCbhVl26Y8ntFBm2vJBCtB4X04g5Wwg,2638
26
+ kodit/embedding/embedding_provider/local_embedding_provider.py,sha256=4ER-UPq506Y0TWU6qcs0nUqw6bSKQkSrdog-DhNQWM8,1906
27
+ kodit/embedding/embedding_provider/openai_embedding_provider.py,sha256=bmUpegDgaF5Qj9uWcj1az4ADA2cKHUjraaMjGGPr83U,2076
28
+ kodit/indexing/__init__.py,sha256=cPyi2Iej3G1JFWlWr7X80_UrsMaTu5W5rBwgif1B3xo,75
29
+ kodit/indexing/indexing_models.py,sha256=6NX9HVcj6Pu9ePwHC7n-PWSyAgukpJq0nCNmUIigtbo,1282
30
+ kodit/indexing/indexing_repository.py,sha256=4RJ3zY8p6QxHrYW7dDjru_w94Eu19v2gQ4mdlTgcXvY,6331
31
+ kodit/indexing/indexing_service.py,sha256=T_dxOzNW_0OCpR4Fha1hHuNkmtLcDMZwL6t5xeu5VXQ,6613
32
+ kodit/migrations/README,sha256=ISVtAOvqvKk_5ThM5ioJE-lMkvf9IbknFUFVU_vPma4,58
33
+ kodit/migrations/__init__.py,sha256=lP5MuwlyWRMO6UcDWnQcQ3G-GYHcFb6rl9gYPHJ1sjo,40
34
+ kodit/migrations/env.py,sha256=w1M7OZh-ZeR2dPHS0ByXAUxQjfZQ8xIzMseWuzLDTWw,2469
35
+ kodit/migrations/script.py.mako,sha256=zWziKtiwYKEWuwPV_HBNHwa9LCT45_bi01-uSNFaOOE,703
36
+ kodit/migrations/versions/7c3bbc2ab32b_add_embeddings_table.py,sha256=-61qol9PfQKILCDQRA5jEaats9aGZs9Wdtp-j-38SF4,1644
37
+ kodit/migrations/versions/85155663351e_initial.py,sha256=Cg7zlF871o9ShV5rQMQ1v7hRV7fI59veDY9cjtTrs-8,3306
38
+ kodit/migrations/versions/__init__.py,sha256=9-lHzptItTzq_fomdIRBegQNm4Znx6pVjwD4MiqRIdo,36
39
+ kodit/search/__init__.py,sha256=4QbdjbrlhNKMovmuKHxJnUeZT7KNjTTFU0GdnuwUHdQ,36
40
+ kodit/search/search_repository.py,sha256=6q0k7JMTM_7hPK2TSA30CykGbc5N16kCL7HTjlbai0w,1563
41
+ kodit/search/search_service.py,sha256=-XlbP_50e1dKFJ5jBvex5FjLnffW43LcwQV_SeYNFB0,3944
42
+ kodit/snippets/__init__.py,sha256=-2coNoCRjTixU9KcP6alpmt7zqf37tCRWH3D7FPJ8dg,48
43
+ kodit/snippets/method_snippets.py,sha256=EVHhSNWahAC5nSXv9fWVFJY2yq25goHdCSCuENC07F8,4145
44
+ kodit/snippets/snippets.py,sha256=mwN0bM1Msu8ZeEsUHyQ7tx3Hj3vZsm8G7Wu4eWSkLY8,1539
45
+ kodit/snippets/languages/__init__.py,sha256=Bj5KKZSls2MQ8ZY1S_nHg447MgGZW-2WZM-oq6vjwwA,1187
46
+ kodit/snippets/languages/csharp.scm,sha256=gbBN4RiV1FBuTJF6orSnDFi8H9JwTw-d4piLJYsWUsc,222
47
+ kodit/snippets/languages/python.scm,sha256=ee85R9PBzwye3IMTE7-iVoKWd_ViU3EJISTyrFGrVeo,429
48
+ kodit/source/__init__.py,sha256=1NTZyPdjThVQpZO1Mp1ColVsS7sqYanOVLqnoqV9Ipo,83
49
+ kodit/source/source_models.py,sha256=xb42CaNDO1CUB8SIW-xXMrB6Ji8cFw-yeJ550xBEg9Q,2398
50
+ kodit/source/source_repository.py,sha256=0EksMpoLzdkfe8S4eeCm4Sf7TuxsOzOzaF4BBsMYo-4,3163
51
+ kodit/source/source_service.py,sha256=u_GaH07ewakThQJRfT8O_yZ54A52qLtJuM1bF3xUT2A,9633
52
+ kodit/util/__init__.py,sha256=bPu6CtqDWCRGU7VgW2_aiQrCBi8G89FS6k1PjvDajJ0,37
53
+ kodit/util/spinner.py,sha256=R9bzrHtBiIH6IfLbmsIVHL53s8vg-tqW4lwGGALu4dw,1932
54
+ kodit-0.1.15.dist-info/METADATA,sha256=8E-bw8L-Df5Hdt16R5IWkyw7uUAr13CwYfcEyFExaPw,2380
55
+ kodit-0.1.15.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
56
+ kodit-0.1.15.dist-info/entry_points.txt,sha256=hoTn-1aKyTItjnY91fnO-rV5uaWQLQ-Vi7V5et2IbHY,40
57
+ kodit-0.1.15.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
58
+ kodit-0.1.15.dist-info/RECORD,,