alita-sdk 0.3.230__py3-none-any.whl → 0.3.232__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.
@@ -8,6 +8,7 @@ from pydantic import BaseModel, model_validator, Field
8
8
  from ..langchain.tools.vector import VectorAdapter
9
9
  from langchain_core.messages import HumanMessage
10
10
  from alita_sdk.tools.elitea_base import BaseToolApiWrapper
11
+ from alita_sdk.tools.vector_adapters.VectorStoreAdapter import VectorStoreAdapterFactory
11
12
  from logging import getLogger
12
13
 
13
14
  from ..utils.logging import dispatch_custom_event
@@ -141,11 +142,14 @@ class VectorStoreWrapper(BaseToolApiWrapper):
141
142
  dataset: str = None
142
143
  embedding: Any = None
143
144
  vectorstore: Any = None
145
+ # Review usage of old adapter
144
146
  vectoradapter: Any = None
145
147
  pg_helper: Any = None
146
148
  embeddings: Any = None
147
149
  process_document_func: Optional[Callable] = None
148
-
150
+ # New adapter for vector database operations
151
+ vector_adapter: Any = None
152
+
149
153
  @model_validator(mode='before')
150
154
  @classmethod
151
155
  def validate_toolkit(cls, values):
@@ -170,6 +174,8 @@ class VectorStoreWrapper(BaseToolApiWrapper):
170
174
  embeddings=values['embeddings'],
171
175
  quota_params=None,
172
176
  )
177
+ # Initialize the new vector adapter
178
+ values['vector_adapter'] = VectorStoreAdapterFactory.create_adapter(values['vectorstore_type'])
173
179
  logger.debug(f"Vectorstore wrapper initialized: {values}")
174
180
  return values
175
181
 
@@ -196,52 +202,22 @@ class VectorStoreWrapper(BaseToolApiWrapper):
196
202
  f"Remove collection '{self.dataset}'",
197
203
  tool_name="_remove_collection"
198
204
  )
199
- from sqlalchemy import text
200
- from sqlalchemy.orm import Session
201
-
202
- schema_name = self.vectorstore.collection_name
203
- with Session(self.vectorstore.session_maker.bind) as session:
204
- drop_schema_query = text(f"DROP SCHEMA IF EXISTS {schema_name} CASCADE;")
205
- session.execute(drop_schema_query)
206
- session.commit()
207
- logger.info(f"Schema '{schema_name}' has been dropped.")
205
+ self.vector_adapter.remove_collection(self, self.dataset)
208
206
  self._log_data(
209
207
  f"Collection '{self.dataset}' has been removed. ",
210
208
  tool_name="_remove_collection"
211
209
  )
212
210
 
213
- def _get_indexed_ids(self, store):
211
+ def _get_indexed_ids(self, collection_suffix: Optional[str] = '') -> List[str]:
214
212
  """Get all indexed document IDs from vectorstore"""
213
+ return self.vector_adapter.get_indexed_ids(self, collection_suffix)
215
214
 
216
- # Check if this is a PGVector store
217
- if hasattr(store, 'session_maker') and hasattr(store, 'EmbeddingStore'):
218
- return self._get_pgvector_indexed_ids(store)
219
- else:
220
- # Fall back to Chroma implementation
221
- return self._get_chroma_indexed_ids(store)
222
-
223
- def _get_pgvector_indexed_ids(self, store):
224
- """Get all indexed document IDs from PGVector"""
225
- from sqlalchemy.orm import Session
226
-
227
- try:
228
- with Session(store.session_maker.bind) as session:
229
- ids = session.query(store.EmbeddingStore.id).all()
230
- return [str(id_tuple[0]) for id_tuple in ids]
231
- except Exception as e:
232
- logger.error(f"Failed to get indexed IDs from PGVector: {str(e)}")
233
- return []
215
+ def list_collections(self) -> List[str]:
216
+ """List all collections in the vectorstore."""
234
217
 
235
- def _get_chroma_indexed_ids(self, store):
236
- """Get all indexed document IDs from Chroma"""
237
- try:
238
- data = store.get(include=[]) # Only get IDs, no metadata
239
- return data.get('ids', [])
240
- except Exception as e:
241
- logger.error(f"Failed to get indexed IDs from Chroma: {str(e)}")
242
- return []
218
+ return self.vector_adapter.list_collections(self)
243
219
 
244
- def _clean_collection(self):
220
+ def _clean_collection(self, collection_suffix: str = ''):
245
221
  """
246
222
  Clean the vectorstore collection by deleting all indexed data.
247
223
  """
@@ -249,135 +225,28 @@ class VectorStoreWrapper(BaseToolApiWrapper):
249
225
  f"Cleaning collection '{self.dataset}'",
250
226
  tool_name="_clean_collection"
251
227
  )
252
- # This logic deletes all data from the vectorstore collection without removal of collection.
253
- # Collection itself remains available for future indexing.
254
- self.vectoradapter.vectorstore.delete(ids=self._get_indexed_ids(self.vectoradapter.vectorstore))
255
-
228
+ self.vector_adapter.clean_collection(self, collection_suffix)
256
229
  self._log_data(
257
230
  f"Collection '{self.dataset}' has been cleaned. ",
258
231
  tool_name="_clean_collection"
259
232
  )
260
233
 
261
- # TODO: refactor to use common method for different vectorstores in a separate vectorstore wrappers
262
- def _get_indexed_data(self, store):
234
+ def _get_indexed_data(self):
263
235
  """ Get all indexed data from vectorstore for non-code content """
236
+ return self.vector_adapter.get_indexed_data(self)
264
237
 
265
- # Check if this is a PGVector store
266
- if hasattr(store, 'session_maker') and hasattr(store, 'EmbeddingStore'):
267
- return self._get_pgvector_indexed_data(store)
268
- else:
269
- # Fall back to original Chroma implementation
270
- return self._get_chroma_indexed_data(store)
271
-
272
- def _get_pgvector_indexed_data(self, store):
273
- """ Get all indexed data from PGVector for non-code content """
274
- from sqlalchemy.orm import Session
275
-
276
- result = {}
277
- try:
278
- self._log_data("Retrieving already indexed data from PGVector vectorstore",
279
- tool_name="index_documents")
280
-
281
- with Session(store.session_maker.bind) as session:
282
- docs = session.query(
283
- store.EmbeddingStore.id,
284
- store.EmbeddingStore.document,
285
- store.EmbeddingStore.cmetadata
286
- ).all()
287
-
288
- # Process the retrieved data
289
- for doc in docs:
290
- db_id = doc.id
291
- meta = doc.cmetadata or {}
292
-
293
- # Get document id from metadata
294
- doc_id = str(meta.get('id', db_id))
295
- dependent_docs = meta.get(IndexerKeywords.DEPENDENT_DOCS.value, [])
296
- if dependent_docs:
297
- dependent_docs = [d.strip() for d in dependent_docs.split(';') if d.strip()]
298
- parent_id = meta.get(IndexerKeywords.PARENT.value, -1)
299
-
300
- chunk_id = meta.get('chunk_id')
301
- if doc_id in result and chunk_id:
302
- # If document with the same id already saved, add db_id for current one as chunk
303
- result[doc_id]['all_chunks'].append(db_id)
304
- else:
305
- result[doc_id] = {
306
- 'metadata': meta,
307
- 'id': db_id,
308
- 'all_chunks': [db_id],
309
- IndexerKeywords.DEPENDENT_DOCS.value: dependent_docs,
310
- IndexerKeywords.PARENT.value: parent_id
311
- }
312
-
313
- except Exception as e:
314
- logger.error(f"Failed to get indexed data from PGVector: {str(e)}. Continuing with empty index.")
315
-
316
- return result
317
-
318
- def _get_chroma_indexed_data(self, store):
319
- """ Get all indexed data from Chroma for non-code content """
320
- result = {}
321
- try:
322
- self._log_data("Retrieving already indexed data from Chroma vectorstore",
323
- tool_name="index_documents")
324
- data = store.get(include=['metadatas'])
325
-
326
- # Re-structure data to be more usable
327
- for meta, db_id in zip(data['metadatas'], data['ids']):
328
- # Get document id from metadata
329
- doc_id = str(meta['id'])
330
- dependent_docs = meta.get(IndexerKeywords.DEPENDENT_DOCS.value, [])
331
- if dependent_docs:
332
- dependent_docs = [d.strip() for d in dependent_docs.split(';') if d.strip()]
333
- parent_id = meta.get(IndexerKeywords.PARENT.value, -1)
334
-
335
- chunk_id = meta.get('chunk_id')
336
- if doc_id in result and chunk_id:
337
- # If document with the same id already saved, add db_id for current one as chunk
338
- result[doc_id]['all_chunks'].append(db_id)
339
- else:
340
- result[doc_id] = {
341
- 'metadata': meta,
342
- 'id': db_id,
343
- 'all_chunks': [db_id],
344
- IndexerKeywords.DEPENDENT_DOCS.value: dependent_docs,
345
- IndexerKeywords.PARENT.value: parent_id
346
- }
347
- except Exception as e:
348
- logger.error(f"Failed to get indexed data from Chroma: {str(e)}. Continuing with empty index.")
349
-
350
- return result
351
-
352
- def _get_code_indexed_data(self, store) -> Dict[str, Dict[str, Any]]:
238
+ def _get_code_indexed_data(self) -> Dict[str, Dict[str, Any]]:
353
239
  """ Get all indexed data from vectorstore for code content """
240
+ return self.vector_adapter.get_code_indexed_data(self)
354
241
 
355
- # get already indexed data
356
- result = {}
357
- try:
358
- self._log_data("Retrieving already indexed code data from vectorstore",
359
- tool_name="index_documents")
360
- data = store.get(include=['metadatas'])
361
- # re-structure data to be more usable
362
- for meta, db_id in zip(data['metadatas'], data['ids']):
363
- filename = meta['filename']
364
- commit_hash = meta.get('commit_hash')
365
- if filename not in result:
366
- result[filename] = {
367
- 'commit_hashes': [],
368
- 'ids': []
369
- }
370
- if commit_hash is not None:
371
- result[filename]['commit_hashes'].append(commit_hash)
372
- result[filename]['ids'].append(db_id)
373
- except Exception as e:
374
- logger.error(f"Failed to get indexed code data from vectorstore: {str(e)}. Continuing with empty index.")
375
- return result
242
+ def _add_to_collection(self, entry_id, new_collection_value):
243
+ """Add a new collection name to the `collection` key in the `metadata` column."""
244
+ self.vector_adapter.add_to_collection(self, entry_id, new_collection_value)
376
245
 
377
246
  def _reduce_duplicates(
378
247
  self,
379
248
  documents: Generator[Any, None, None],
380
- store,
249
+ collection_suffix: str,
381
250
  get_indexed_data: Callable,
382
251
  key_fn: Callable,
383
252
  compare_fn: Callable,
@@ -386,7 +255,7 @@ class VectorStoreWrapper(BaseToolApiWrapper):
386
255
  ) -> List[Any]:
387
256
  """Generic duplicate reduction logic for documents."""
388
257
  self._log_data(log_msg, tool_name="index_documents")
389
- indexed_data = get_indexed_data(store)
258
+ indexed_data = get_indexed_data()
390
259
  indexed_keys = set(indexed_data.keys())
391
260
  if not indexed_keys:
392
261
  self._log_data("Vectorstore is empty, indexing all incoming documents", tool_name="index_documents")
@@ -397,8 +266,15 @@ class VectorStoreWrapper(BaseToolApiWrapper):
397
266
 
398
267
  for document in documents:
399
268
  key = key_fn(document)
400
- if key in indexed_keys:
269
+ if key in indexed_keys and collection_suffix == indexed_data[key]['metadata'].get('collection'):
401
270
  if compare_fn(document, indexed_data[key]):
271
+ # Disabled addition of new collection to already indexed documents
272
+ # # check metadata.collection and update if needed
273
+ # for update_collection_id in remove_ids_fn(indexed_data, key):
274
+ # self._add_to_collection(
275
+ # update_collection_id,
276
+ # collection_suffix
277
+ # )
402
278
  continue
403
279
  final_docs.append(document)
404
280
  docs_to_remove.update(remove_ids_fn(indexed_data, key))
@@ -410,14 +286,14 @@ class VectorStoreWrapper(BaseToolApiWrapper):
410
286
  f"Removing {len(docs_to_remove)} documents from vectorstore that are already indexed with different updated_on.",
411
287
  tool_name="index_documents"
412
288
  )
413
- store.delete(ids=list(docs_to_remove))
289
+ self.vectorstore.delete(ids=list(docs_to_remove))
414
290
 
415
291
  return final_docs
416
292
 
417
- def _reduce_non_code_duplicates(self, documents: Generator[Any, None, None], store) -> List[Any]:
293
+ def _reduce_non_code_duplicates(self, documents: Generator[Any, None, None], collection_suffix: str) -> List[Any]:
418
294
  return self._reduce_duplicates(
419
295
  documents,
420
- store,
296
+ collection_suffix,
421
297
  self._get_indexed_data,
422
298
  lambda doc: doc.metadata.get('id'),
423
299
  lambda doc, idx: (
@@ -434,10 +310,10 @@ class VectorStoreWrapper(BaseToolApiWrapper):
434
310
  log_msg="Verification of documents to index started"
435
311
  )
436
312
 
437
- def _reduce_code_duplicates(self, documents: Generator[Any, None, None], store) -> List[Any]:
313
+ def _reduce_code_duplicates(self, documents: Generator[Any, None, None], collection_suffix: str) -> List[Any]:
438
314
  return self._reduce_duplicates(
439
315
  documents,
440
- store,
316
+ collection_suffix,
441
317
  self._get_code_indexed_data,
442
318
  lambda doc: doc.metadata.get('filename'),
443
319
  lambda doc, idx: (
@@ -449,7 +325,7 @@ class VectorStoreWrapper(BaseToolApiWrapper):
449
325
  log_msg="Verification of code documents to index started"
450
326
  )
451
327
 
452
- def index_documents(self, documents: Generator[Document, None, None], progress_step: int = 20, clean_index: bool = True, is_code: bool = False):
328
+ def index_documents(self, documents: Generator[Document, None, None], collection_suffix: str, progress_step: int = 20, clean_index: bool = True, is_code: bool = False):
453
329
  """ Index documents in the vectorstore.
454
330
 
455
331
  Args:
@@ -465,7 +341,7 @@ class VectorStoreWrapper(BaseToolApiWrapper):
465
341
  logger.info("Cleaning index before re-indexing all documents.")
466
342
  self._log_data("Cleaning index before re-indexing all documents. Previous index will be removed", tool_name="index_documents")
467
343
  try:
468
- self._clean_collection()
344
+ self._clean_collection(collection_suffix)
469
345
  self.vectoradapter.persist()
470
346
  self.vectoradapter.vacuum()
471
347
  self._log_data("Previous index has been removed",
@@ -476,8 +352,8 @@ class VectorStoreWrapper(BaseToolApiWrapper):
476
352
  documents = list(documents)
477
353
  else:
478
354
  # remove duplicates based on metadata 'id' and 'updated_on' or 'commit_hash' fields
479
- documents = self._reduce_code_duplicates(documents, self.vectoradapter.vectorstore) if is_code \
480
- else self._reduce_non_code_duplicates(documents, self.vectoradapter.vectorstore)
355
+ documents = self._reduce_code_duplicates(documents, collection_suffix) if is_code \
356
+ else self._reduce_non_code_duplicates(documents, collection_suffix)
481
357
 
482
358
  if not documents or len(documents) == 0:
483
359
  logger.info("No new documents to index after duplicate check.")
@@ -498,6 +374,15 @@ class VectorStoreWrapper(BaseToolApiWrapper):
498
374
  logger.debug(self.vectoradapter)
499
375
 
500
376
  documents = documents + list(dependent_docs_generator)
377
+
378
+ # if collection_suffix is provided, add it to metadata of each document
379
+ if collection_suffix:
380
+ for doc in documents:
381
+ if not doc.metadata.get('collection'):
382
+ doc.metadata['collection'] = collection_suffix
383
+ else:
384
+ doc.metadata['collection'] += f";{collection_suffix}"
385
+
501
386
  total_docs = len(documents)
502
387
  documents_count = 0
503
388
  _documents = []
@@ -511,8 +396,7 @@ class VectorStoreWrapper(BaseToolApiWrapper):
511
396
  try:
512
397
  _documents.append(document)
513
398
  if len(_documents) >= self.max_docs_per_add:
514
- add_documents(vectorstore=self.vectoradapter.vectorstore, documents=_documents)
515
- self.vectoradapter.persist()
399
+ add_documents(vectorstore=self.vectorstore, documents=_documents)
516
400
  _documents = []
517
401
 
518
402
  percent = math.floor((documents_count / total_docs) * 100)
@@ -526,8 +410,7 @@ class VectorStoreWrapper(BaseToolApiWrapper):
526
410
  logger.error(f"Error: {format_exc()}")
527
411
  return {"status": "error", "message": f"Error: {format_exc()}"}
528
412
  if _documents:
529
- add_documents(vectorstore=self.vectoradapter.vectorstore, documents=_documents)
530
- self.vectoradapter.persist()
413
+ add_documents(vectorstore=self.vectorstore, documents=_documents)
531
414
  return {"status": "ok", "message": f"successfully indexed {documents_count} documents"}
532
415
 
533
416
  def search_documents(self, query:str, doctype: str = 'code',
@@ -562,7 +445,7 @@ class VectorStoreWrapper(BaseToolApiWrapper):
562
445
  }
563
446
 
564
447
  try:
565
- document_items = self.vectoradapter.vectorstore.similarity_search_with_score(
448
+ document_items = self.vectorstore.similarity_search_with_score(
566
449
  query, filter=document_filter, k=search_top
567
450
  )
568
451
  # Add document results to unique docs
@@ -595,7 +478,7 @@ class VectorStoreWrapper(BaseToolApiWrapper):
595
478
  }
596
479
 
597
480
  try:
598
- chunk_items = self.vectoradapter.vectorstore.similarity_search_with_score(
481
+ chunk_items = self.vectorstore.similarity_search_with_score(
599
482
  query, filter=chunk_filter, k=search_top
600
483
  )
601
484
 
@@ -628,7 +511,7 @@ class VectorStoreWrapper(BaseToolApiWrapper):
628
511
  }
629
512
 
630
513
  try:
631
- fetch_items = self.vectoradapter.vectorstore.similarity_search_with_score(
514
+ fetch_items = self.vectorstore.similarity_search_with_score(
632
515
  query, filter=doc_filter, k=1
633
516
  )
634
517
  if fetch_items:
@@ -642,7 +525,7 @@ class VectorStoreWrapper(BaseToolApiWrapper):
642
525
  else:
643
526
  # Default search behavior (unchanged)
644
527
  max_search_results = 30 if search_top * 3 > 30 else search_top * 3
645
- vector_items = self.vectoradapter.vectorstore.similarity_search_with_score(
528
+ vector_items = self.vectorstore.similarity_search_with_score(
646
529
  query, filter=filter, k=max_search_results
647
530
  )
648
531
 
@@ -862,4 +745,5 @@ class VectorStoreWrapper(BaseToolApiWrapper):
862
745
  "description": "Get summary of search results using stepback technique",
863
746
  "args_schema": StepBackSearchDocumentsModel
864
747
  }
865
- ]
748
+ ]
749
+
@@ -30,13 +30,13 @@ LoaderSchema = create_model(
30
30
  # Base Vector Store Schema Models
31
31
  BaseIndexParams = create_model(
32
32
  "BaseIndexParams",
33
- collection_suffix=(Optional[str], Field(description="Optional suffix for collection name (max 7 characters)", default="", max_length=7)),
33
+ collection_suffix=(str, Field(description="Suffix for collection name (max 7 characters) used to separate datasets", min_length=1, max_length=7)),
34
34
  vectorstore_type=(Optional[str], Field(description="Vectorstore type (Chroma, PGVector, Elastic, etc.)", default="PGVector")),
35
35
  )
36
36
 
37
37
  BaseCodeIndexParams = create_model(
38
38
  "BaseCodeIndexParams",
39
- collection_suffix=(Optional[str], Field(description="Optional suffix for collection name (max 7 characters)", default="", max_length=7)),
39
+ collection_suffix=(str, Field(description="Suffix for collection name (max 7 characters) used to separate datasets", min_length=1, max_length=7)),
40
40
  vectorstore_type=(Optional[str], Field(description="Vectorstore type (Chroma, PGVector, Elastic, etc.)", default="PGVector")),
41
41
  branch=(Optional[str], Field(description="Branch to index files from. Defaults to active branch if None.", default=None)),
42
42
  whitelist=(Optional[List[str]], Field(description="File extensions or paths to include. Defaults to all files if None.", default=None)),
@@ -51,7 +51,9 @@ RemoveIndexParams = create_model(
51
51
  BaseSearchParams = create_model(
52
52
  "BaseSearchParams",
53
53
  query=(str, Field(description="Query text to search in the index")),
54
- collection_suffix=(Optional[str], Field(description="Optional suffix for collection name (max 7 characters)", default="", max_length=7)),
54
+ collection_suffix=(Optional[str], Field(
55
+ description="Optional suffix for collection name (max 7 characters). Leave empty to search across all datasets",
56
+ default="", max_length=7)),
55
57
  vectorstore_type=(Optional[str], Field(description="Vectorstore type (Chroma, PGVector, Elastic, etc.)", default="PGVector")),
56
58
  filter=(Optional[dict | str], Field(
57
59
  description="Filter to apply to the search results. Can be a dictionary or a JSON string.",
@@ -219,6 +221,7 @@ class BaseVectorStoreToolApiWrapper(BaseToolApiWrapper):
219
221
  embedding_model: Optional[str] = "HuggingFaceEmbeddings"
220
222
  embedding_model_params: Optional[Dict[str, Any]] = {"model_name": "sentence-transformers/all-MiniLM-L6-v2"}
221
223
  vectorstore_type: Optional[str] = "PGVector"
224
+ _vector_store: Optional[Any] = None
222
225
 
223
226
  def __init__(self, **kwargs):
224
227
  super().__init__(**kwargs)
@@ -297,9 +300,9 @@ class BaseVectorStoreToolApiWrapper(BaseToolApiWrapper):
297
300
  collection_suffix = kwargs.get("collection_suffix")
298
301
  progress_step = kwargs.get("progress_step")
299
302
  clean_index = kwargs.get("clean_index")
300
- vs = self._init_vector_store(collection_suffix, embeddings=embedding)
303
+ vs = self._init_vector_store(embeddings=embedding)
301
304
  #
302
- return vs.index_documents(docs, progress_step=progress_step, clean_index=clean_index)
305
+ return vs.index_documents(docs, collection_suffix=collection_suffix, progress_step=progress_step, clean_index=clean_index)
303
306
 
304
307
  def _process_documents(self, documents: List[Document]) -> Generator[Document, None, None]:
305
308
  """
@@ -333,48 +336,37 @@ class BaseVectorStoreToolApiWrapper(BaseToolApiWrapper):
333
336
 
334
337
 
335
338
  # TODO: init store once and re-use the instance
336
- def _init_vector_store(self, collection_suffix: str = "", embeddings: Optional[Any] = None):
339
+ def _init_vector_store(self, embeddings: Optional[Any] = None):
337
340
  """Initializes the vector store wrapper with the provided parameters."""
338
341
  try:
339
342
  from alita_sdk.runtime.tools.vectorstore import VectorStoreWrapper
340
343
  except ImportError:
341
344
  from alita_sdk.runtime.tools.vectorstore import VectorStoreWrapper
342
345
 
343
- # Validate collection_suffix length
344
- if collection_suffix and len(collection_suffix.strip()) > 7:
345
- raise ToolException("collection_suffix must be 7 characters or less")
346
-
347
- # Create collection name with suffix if provided
348
- collection_name = str(self.collection_name)
349
- if collection_suffix and collection_suffix.strip():
350
- collection_name = f"{self.collection_name}_{collection_suffix.strip()}"
351
-
352
- # Get database-specific parameters using adapter
353
- connection_string = self.connection_string.get_secret_value() if self.connection_string else None
354
- vectorstore_params = self._adapter.get_vectorstore_params(collection_name, connection_string)
355
-
356
- return VectorStoreWrapper(
357
- llm=self.llm,
358
- vectorstore_type=self.vectorstore_type,
359
- embedding_model=self.embedding_model,
360
- embedding_model_params=self.embedding_model_params,
361
- vectorstore_params=vectorstore_params,
362
- embeddings=embeddings,
363
- process_document_func=self._process_documents,
364
- )
346
+ if not self._vector_store:
347
+ connection_string = self.connection_string.get_secret_value() if self.connection_string else None
348
+ vectorstore_params = self._adapter.get_vectorstore_params(self.collection_name, connection_string)
349
+ self._vector_store = VectorStoreWrapper(
350
+ llm=self.llm,
351
+ vectorstore_type=self.vectorstore_type,
352
+ embedding_model=self.embedding_model,
353
+ embedding_model_params=self.embedding_model_params,
354
+ vectorstore_params=vectorstore_params,
355
+ embeddings=embeddings,
356
+ process_document_func=self._process_documents,
357
+ )
358
+ return self._vector_store
365
359
 
366
360
  def remove_index(self, collection_suffix: str = ""):
367
361
  """Cleans the indexed data in the collection."""
368
- vectorstore_wrapper = self._init_vector_store(collection_suffix)
369
- collection_name = f"{self.collection_name}_{collection_suffix}" if collection_suffix else str(self.collection_name)
370
- self._adapter.remove_collection(vectorstore_wrapper, collection_name)
371
- return (f"Collection '{collection_name}' has been removed from the vector store.\n"
362
+ self._init_vector_store()._clean_collection(collection_suffix=collection_suffix)
363
+ return (f"Collection '{collection_suffix}' has been removed from the vector store.\n"
372
364
  f"Available collections: {self.list_collections()}")
373
365
 
374
366
  def list_collections(self):
375
367
  """Lists all collections in the vector store."""
376
368
  vectorstore_wrapper = self._init_vector_store()
377
- return self._adapter.list_collections(vectorstore_wrapper, self.collection_name or "")
369
+ return vectorstore_wrapper.list_collections()
378
370
 
379
371
  def search_index(self,
380
372
  query: str,
@@ -386,7 +378,14 @@ class BaseVectorStoreToolApiWrapper(BaseToolApiWrapper):
386
378
  extended_search: Optional[List[str]] = None,
387
379
  **kwargs):
388
380
  """ Searches indexed documents in the vector store."""
389
- vectorstore = self._init_vector_store(collection_suffix)
381
+ vectorstore = self._init_vector_store()
382
+ # build filter on top of collection_suffix
383
+ filter = filter if isinstance(filter, dict) else json.loads(filter)
384
+ if collection_suffix:
385
+ filter.update({"collection": {
386
+ "$eq": collection_suffix.strip()
387
+ }})
388
+
390
389
  found_docs = vectorstore.search_documents(
391
390
  query,
392
391
  doctype=self.doctype,
@@ -499,6 +498,8 @@ class BaseVectorStoreToolApiWrapper(BaseToolApiWrapper):
499
498
 
500
499
  class BaseCodeToolApiWrapper(BaseVectorStoreToolApiWrapper):
501
500
 
501
+ doctype: Optional[str] = 'code'
502
+
502
503
  def _get_files(self):
503
504
  raise NotImplementedError("Subclasses should implement this method")
504
505
 
@@ -579,22 +580,20 @@ class BaseCodeToolApiWrapper(BaseVectorStoreToolApiWrapper):
579
580
  return parse_code_files_for_db(file_content_generator())
580
581
 
581
582
  def index_data(self,
583
+ collection_suffix: str,
582
584
  branch: Optional[str] = None,
583
585
  whitelist: Optional[List[str]] = None,
584
586
  blacklist: Optional[List[str]] = None,
585
- collection_suffix: str = "",
586
587
  **kwargs) -> str:
587
588
  """Index repository files in the vector store using code parsing."""
588
589
 
589
-
590
-
591
590
  documents = self.loader(
592
591
  branch=branch,
593
592
  whitelist=whitelist,
594
593
  blacklist=blacklist
595
594
  )
596
- vectorstore = self._init_vector_store(collection_suffix)
597
- return vectorstore.index_documents(documents, clean_index=False, is_code=True)
595
+ vectorstore = self._init_vector_store()
596
+ return vectorstore.index_documents(documents, collection_suffix=collection_suffix, clean_index=False, is_code=True)
598
597
 
599
598
  def _get_vector_search_tools(self):
600
599
  """
@@ -37,9 +37,9 @@ class AlitaGitHubAPIWrapper(BaseCodeToolApiWrapper):
37
37
  Wrapper for GitHub API that integrates both REST and GraphQL functionality.
38
38
  """
39
39
  # Authentication config
40
- github_access_token: Optional[str] = None
41
- github_username: Optional[str] = None
42
- github_password: Optional[str] = None
40
+ github_access_token: Optional[SecretStr] = None
41
+ github_username: Optional[SecretStr] = None
42
+ github_password: Optional[SecretStr] = None
43
43
  github_app_id: Optional[str] = None
44
44
  github_app_private_key: Optional[str] = None
45
45
  github_base_url: Optional[str] = None
@@ -49,19 +49,9 @@ class AlitaGitHubAPIWrapper(BaseCodeToolApiWrapper):
49
49
  active_branch: Optional[str] = None
50
50
  github_base_branch: Optional[str] = None
51
51
 
52
- # Add LLM instance
53
- llm: Optional[Any] = None
54
52
  # Alita instance
55
53
  alita: Optional[Any] = None
56
54
 
57
- # Vector store configuration
58
- connection_string: Optional[SecretStr] = None
59
- collection_name: Optional[str] = None
60
- doctype: Optional[str] = 'code' # GitHub uses 'code' doctype
61
- embedding_model: Optional[str] = "HuggingFaceEmbeddings"
62
- embedding_model_params: Optional[Dict[str, Any]] = {"model_name": "sentence-transformers/all-MiniLM-L6-v2"}
63
- vectorstore_type: Optional[str] = "PGVector"
64
-
65
55
  # Client instances - renamed without leading underscores and marked as exclude=True
66
56
  github_client_instance: Optional[GitHubClient] = Field(default=None, exclude=True)
67
57
  graphql_client_instance: Optional[GraphQLClientWrapper] = Field(default=None, exclude=True)
@@ -84,12 +74,12 @@ class AlitaGitHubAPIWrapper(BaseCodeToolApiWrapper):
84
74
  from langchain.utils import get_from_dict_or_env
85
75
 
86
76
  # Get all authentication values
87
- github_access_token = get_from_dict_or_env(values, "github_access_token", "GITHUB_ACCESS_TOKEN", default='')
88
- github_username = get_from_dict_or_env(values, "github_username", "GITHUB_USERNAME", default='')
89
- github_password = get_from_dict_or_env(values, "github_password", "GITHUB_PASSWORD", default='')
90
- github_app_id = get_from_dict_or_env(values, "github_app_id", "GITHUB_APP_ID", default='')
91
- github_app_private_key = get_from_dict_or_env(values, "github_app_private_key", "GITHUB_APP_PRIVATE_KEY", default='')
92
- github_base_url = get_from_dict_or_env(values, "github_base_url", "GITHUB_BASE_URL", default='https://api.github.com')
77
+ github_access_token = get_from_dict_or_env(values, ["access_token", "github_access_token"], "GITHUB_ACCESS_TOKEN", default='')
78
+ github_username = get_from_dict_or_env(values, ["username", "github_username"], "GITHUB_USERNAME", default='')
79
+ github_password = get_from_dict_or_env(values, ["password", "github_password"], "GITHUB_PASSWORD", default='')
80
+ github_app_id = get_from_dict_or_env(values, ["app_id", "github_app_id"], "GITHUB_APP_ID", default='')
81
+ github_app_private_key = get_from_dict_or_env(values, ["app_private_key", "github_app_private_key"], "GITHUB_APP_PRIVATE_KEY", default='')
82
+ github_base_url = get_from_dict_or_env(values, ["base_url", "github_base_url"], "GITHUB_BASE_URL", default='https://api.github.com')
93
83
 
94
84
  auth_config = GitHubAuthConfig(
95
85
  github_access_token=github_access_token,
@@ -1,5 +1,8 @@
1
1
  from abc import ABC, abstractmethod
2
- from typing import Any, Dict, Optional
2
+ from typing import Any, Dict, Optional, List
3
+ from logging import getLogger
4
+
5
+ logger = getLogger(__name__)
3
6
 
4
7
 
5
8
  class VectorStoreAdapter(ABC):
@@ -20,6 +23,31 @@ class VectorStoreAdapter(ABC):
20
23
  """Remove a collection from the vector store."""
21
24
  pass
22
25
 
26
+ @abstractmethod
27
+ def get_indexed_ids(self, vectorstore_wrapper, collection_suffix: Optional[str] = '') -> List[str]:
28
+ """Get all indexed document IDs from vectorstore"""
29
+ pass
30
+
31
+ @abstractmethod
32
+ def clean_collection(self, vectorstore_wrapper, collection_suffix: str = ''):
33
+ """Clean the vectorstore collection by deleting all indexed data."""
34
+ pass
35
+
36
+ @abstractmethod
37
+ def get_indexed_data(self, vectorstore_wrapper):
38
+ """Get all indexed data from vectorstore for non-code content"""
39
+ pass
40
+
41
+ @abstractmethod
42
+ def get_code_indexed_data(self, vectorstore_wrapper) -> Dict[str, Dict[str, Any]]:
43
+ """Get all indexed data from vectorstore for code content"""
44
+ pass
45
+
46
+ @abstractmethod
47
+ def add_to_collection(self, vectorstore_wrapper, entry_id, new_collection_value):
48
+ """Add a new collection name to the metadata"""
49
+ pass
50
+
23
51
 
24
52
  class PGVectorAdapter(VectorStoreAdapter):
25
53
  """Adapter for PGVector database operations."""
@@ -35,23 +63,195 @@ class PGVectorAdapter(VectorStoreAdapter):
35
63
  "connection_string": connection_string
36
64
  }
37
65
 
38
- def list_collections(self, vectorstore_wrapper, collection_name) -> str:
66
+ def list_collections(self, vectorstore_wrapper) -> str:
67
+ from sqlalchemy import func
68
+ from sqlalchemy.orm import Session
69
+
70
+ store = vectorstore_wrapper.vectorstore
71
+ try:
72
+ with Session(store.session_maker.bind) as session:
73
+ collections = (
74
+ session.query(
75
+ func.distinct(func.jsonb_extract_path_text(store.EmbeddingStore.cmetadata, 'collection'))
76
+ )
77
+ .filter(store.EmbeddingStore.cmetadata.isnot(None))
78
+ .all()
79
+ )
80
+ return [collection[0] for collection in collections if collection[0] is not None]
81
+ except Exception as e:
82
+ logger.error(f"Failed to get unique collections from PGVector: {str(e)}")
83
+ return []
84
+
85
+ def remove_collection(self, vectorstore_wrapper, collection_name: str):
39
86
  from sqlalchemy import text
40
87
  from sqlalchemy.orm import Session
41
88
 
89
+ schema_name = vectorstore_wrapper.vectorstore.collection_name
42
90
  with Session(vectorstore_wrapper.vectorstore.session_maker.bind) as session:
43
- get_collections = text(f"""
44
- SELECT table_schema
45
- FROM information_schema.columns
46
- WHERE udt_name = 'vector'
47
- AND table_schema LIKE '%{collection_name}%';
48
- """)
49
- result = session.execute(get_collections)
50
- docs = result.fetchall()
51
- return str(docs)
91
+ drop_schema_query = text(f"DROP SCHEMA IF EXISTS {schema_name} CASCADE;")
92
+ session.execute(drop_schema_query)
93
+ session.commit()
94
+ logger.info(f"Schema '{schema_name}' has been dropped.")
52
95
 
53
- def remove_collection(self, vectorstore_wrapper, collection_name: str):
54
- vectorstore_wrapper._remove_collection()
96
+ def get_indexed_ids(self, vectorstore_wrapper, collection_suffix: Optional[str] = '') -> List[str]:
97
+ """Get all indexed document IDs from PGVector"""
98
+ from sqlalchemy.orm import Session
99
+ from sqlalchemy import func
100
+
101
+ store = vectorstore_wrapper.vectorstore
102
+ try:
103
+ with Session(store.session_maker.bind) as session:
104
+ # Start building the query
105
+ query = session.query(store.EmbeddingStore.id)
106
+ # Apply filter only if collection_suffix is provided
107
+ if collection_suffix:
108
+ query = query.filter(
109
+ func.jsonb_extract_path_text(store.EmbeddingStore.cmetadata, 'collection') == collection_suffix
110
+ )
111
+ ids = query.all()
112
+ return [str(id_tuple[0]) for id_tuple in ids]
113
+ except Exception as e:
114
+ logger.error(f"Failed to get indexed IDs from PGVector: {str(e)}")
115
+ return []
116
+
117
+ def clean_collection(self, vectorstore_wrapper, collection_suffix: str = ''):
118
+ """Clean the vectorstore collection by deleting all indexed data."""
119
+ # This logic deletes all data from the vectorstore collection without removal of collection.
120
+ # Collection itself remains available for future indexing.
121
+ vectorstore_wrapper.vectorstore.delete(ids=self.get_indexed_ids(vectorstore_wrapper, collection_suffix))
122
+
123
+ def is_vectorstore_type(self, vectorstore) -> bool:
124
+ """Check if the vectorstore is a PGVector store."""
125
+ return hasattr(vectorstore, 'session_maker') and hasattr(vectorstore, 'EmbeddingStore')
126
+
127
+ def get_indexed_data(self, vectorstore_wrapper):
128
+ """Get all indexed data from PGVector for non-code content"""
129
+ from sqlalchemy.orm import Session
130
+ from ...runtime.utils.utils import IndexerKeywords
131
+
132
+ result = {}
133
+ try:
134
+ vectorstore_wrapper._log_data("Retrieving already indexed data from PGVector vectorstore",
135
+ tool_name="get_indexed_data")
136
+ store = vectorstore_wrapper.vectorstore
137
+ with Session(store.session_maker.bind) as session:
138
+ docs = session.query(
139
+ store.EmbeddingStore.id,
140
+ store.EmbeddingStore.document,
141
+ store.EmbeddingStore.cmetadata
142
+ ).all()
143
+
144
+ # Process the retrieved data
145
+ for doc in docs:
146
+ db_id = doc.id
147
+ meta = doc.cmetadata or {}
148
+
149
+ # Get document id from metadata
150
+ doc_id = str(meta.get('id', db_id))
151
+ dependent_docs = meta.get(IndexerKeywords.DEPENDENT_DOCS.value, [])
152
+ if dependent_docs:
153
+ dependent_docs = [d.strip() for d in dependent_docs.split(';') if d.strip()]
154
+ parent_id = meta.get(IndexerKeywords.PARENT.value, -1)
155
+
156
+ chunk_id = meta.get('chunk_id')
157
+ if doc_id in result and chunk_id:
158
+ # If document with the same id already saved, add db_id for current one as chunk
159
+ result[doc_id]['all_chunks'].append(db_id)
160
+ else:
161
+ result[doc_id] = {
162
+ 'metadata': meta,
163
+ 'id': db_id,
164
+ 'all_chunks': [db_id],
165
+ IndexerKeywords.DEPENDENT_DOCS.value: dependent_docs,
166
+ IndexerKeywords.PARENT.value: parent_id
167
+ }
168
+
169
+ except Exception as e:
170
+ logger.error(f"Failed to get indexed data from PGVector: {str(e)}. Continuing with empty index.")
171
+
172
+ return result
173
+
174
+ def get_code_indexed_data(self, vectorstore_wrapper) -> Dict[str, Dict[str, Any]]:
175
+ """Get all indexed code data from PGVector."""
176
+ from sqlalchemy.orm import Session
177
+
178
+ result = {}
179
+ try:
180
+ vectorstore_wrapper._log_data("Retrieving already indexed code data from PGVector vectorstore",
181
+ tool_name="index_code_data")
182
+ store = vectorstore_wrapper.vectorstore
183
+ with Session(store.session_maker.bind) as session:
184
+ docs = session.query(
185
+ store.EmbeddingStore.id,
186
+ store.EmbeddingStore.cmetadata
187
+ ).all()
188
+
189
+ for db_id, meta in docs:
190
+ filename = meta.get('filename')
191
+ commit_hash = meta.get('commit_hash')
192
+ if not filename:
193
+ continue
194
+ if filename not in result:
195
+ result[filename] = {
196
+ 'metadata': meta,
197
+ 'commit_hashes': [],
198
+ 'ids': []
199
+ }
200
+ if commit_hash is not None:
201
+ result[filename]['commit_hashes'].append(commit_hash)
202
+ result[filename]['ids'].append(db_id)
203
+ except Exception as e:
204
+ logger.error(f"Failed to get indexed code data from PGVector: {str(e)}. Continuing with empty index.")
205
+ return result
206
+
207
+ def add_to_collection(self, vectorstore_wrapper, entry_id, new_collection_value):
208
+ """Add a new collection name to the `collection` key in the `metadata` column."""
209
+ from sqlalchemy import func
210
+ from sqlalchemy.orm import Session
211
+
212
+ store = vectorstore_wrapper.vectorstore
213
+ try:
214
+ with Session(store.session_maker.bind) as session:
215
+ # Query the current value of the `collection` key
216
+ current_collection_query = session.query(
217
+ func.jsonb_extract_path_text(store.EmbeddingStore.cmetadata, 'collection')
218
+ ).filter(store.EmbeddingStore.id == entry_id).scalar()
219
+
220
+ # If the `collection` key is NULL or doesn't contain the new value, update it
221
+ if current_collection_query is None:
222
+ # If `collection` is NULL, initialize it with the new value
223
+ session.query(store.EmbeddingStore).filter(
224
+ store.EmbeddingStore.id == entry_id
225
+ ).update(
226
+ {
227
+ store.EmbeddingStore.cmetadata: func.jsonb_set(
228
+ func.coalesce(store.EmbeddingStore.cmetadata, '{}'),
229
+ '{collection}', # Path to the `collection` key
230
+ f'"{new_collection_value}"', # New value for the `collection` key
231
+ True # Create the key if it doesn't exist
232
+ )
233
+ }
234
+ )
235
+ elif new_collection_value not in current_collection_query.split(";"):
236
+ # If `collection` exists but doesn't contain the new value, append it
237
+ updated_collection_value = f"{current_collection_query};{new_collection_value}"
238
+ session.query(store.EmbeddingStore).filter(
239
+ store.EmbeddingStore.id == entry_id
240
+ ).update(
241
+ {
242
+ store.EmbeddingStore.cmetadata: func.jsonb_set(
243
+ store.EmbeddingStore.cmetadata,
244
+ '{collection}', # Path to the `collection` key
245
+ f'"{updated_collection_value}"', # Concatenated value as a valid JSON string
246
+ True # Create the key if it doesn't exist
247
+ )
248
+ }
249
+ )
250
+
251
+ session.commit()
252
+ logger.info(f"Successfully updated collection for entry ID {entry_id}.")
253
+ except Exception as e:
254
+ logger.error(f"Failed to update collection for entry ID {entry_id}: {str(e)}")
55
255
 
56
256
 
57
257
  class ChromaAdapter(VectorStoreAdapter):
@@ -64,11 +264,90 @@ class ChromaAdapter(VectorStoreAdapter):
64
264
  }
65
265
 
66
266
  def list_collections(self, vectorstore_wrapper) -> str:
67
- vector_client = vectorstore_wrapper.vectoradapter.vectorstore._client
267
+ vector_client = vectorstore_wrapper.vectorstore._client
68
268
  return ','.join([collection.name for collection in vector_client.list_collections()])
69
269
 
70
270
  def remove_collection(self, vectorstore_wrapper, collection_name: str):
71
- vectorstore_wrapper.vectoradapter.vectorstore.delete_collection()
271
+ vectorstore_wrapper.vectorstore.delete_collection()
272
+
273
+ def get_indexed_ids(self, vectorstore_wrapper, collection_suffix: Optional[str] = '') -> List[str]:
274
+ """Get all indexed document IDs from Chroma"""
275
+ try:
276
+ data = vectorstore_wrapper.vectorstore.get(include=[]) # Only get IDs, no metadata
277
+ return data.get('ids', [])
278
+ except Exception as e:
279
+ logger.error(f"Failed to get indexed IDs from Chroma: {str(e)}")
280
+ return []
281
+
282
+ def clean_collection(self, vectorstore_wrapper, collection_suffix: str = ''):
283
+ """Clean the vectorstore collection by deleting all indexed data."""
284
+ vectorstore_wrapper.vectorstore.delete(ids=self.get_indexed_ids(vectorstore_wrapper, collection_suffix))
285
+
286
+ def get_indexed_data(self, vectorstore_wrapper):
287
+ """Get all indexed data from Chroma for non-code content"""
288
+ from ...runtime.utils.utils import IndexerKeywords
289
+
290
+ result = {}
291
+ try:
292
+ vectorstore_wrapper._log_data("Retrieving already indexed data from Chroma vectorstore",
293
+ tool_name="get_indexed_data")
294
+ data = vectorstore_wrapper.vectorstore.get(include=['metadatas'])
295
+
296
+ # Re-structure data to be more usable
297
+ for meta, db_id in zip(data['metadatas'], data['ids']):
298
+ # Get document id from metadata
299
+ doc_id = str(meta['id'])
300
+ dependent_docs = meta.get(IndexerKeywords.DEPENDENT_DOCS.value, [])
301
+ if dependent_docs:
302
+ dependent_docs = [d.strip() for d in dependent_docs.split(';') if d.strip()]
303
+ parent_id = meta.get(IndexerKeywords.PARENT.value, -1)
304
+
305
+ chunk_id = meta.get('chunk_id')
306
+ if doc_id in result and chunk_id:
307
+ # If document with the same id already saved, add db_id for current one as chunk
308
+ result[doc_id]['all_chunks'].append(db_id)
309
+ else:
310
+ result[doc_id] = {
311
+ 'metadata': meta,
312
+ 'id': db_id,
313
+ 'all_chunks': [db_id],
314
+ IndexerKeywords.DEPENDENT_DOCS.value: dependent_docs,
315
+ IndexerKeywords.PARENT.value: parent_id
316
+ }
317
+ except Exception as e:
318
+ logger.error(f"Failed to get indexed data from Chroma: {str(e)}. Continuing with empty index.")
319
+
320
+ return result
321
+
322
+ def get_code_indexed_data(self, vectorstore_wrapper) -> Dict[str, Dict[str, Any]]:
323
+ """Get all indexed code data from Chroma."""
324
+ result = {}
325
+ try:
326
+ vectorstore_wrapper._log_data("Retrieving already indexed code data from Chroma vectorstore",
327
+ tool_name="index_code_data")
328
+ data = vectorstore_wrapper.vectorstore.get(include=['metadatas'])
329
+ for meta, db_id in zip(data['metadatas'], data['ids']):
330
+ filename = meta.get('filename')
331
+ commit_hash = meta.get('commit_hash')
332
+ if not filename:
333
+ continue
334
+ if filename not in result:
335
+ result[filename] = {
336
+ 'commit_hashes': [],
337
+ 'ids': []
338
+ }
339
+ if commit_hash is not None:
340
+ result[filename]['commit_hashes'].append(commit_hash)
341
+ result[filename]['ids'].append(db_id)
342
+ except Exception as e:
343
+ logger.error(f"Failed to get indexed code data from Chroma: {str(e)}. Continuing with empty index.")
344
+ return result
345
+
346
+ def add_to_collection(self, vectorstore_wrapper, entry_id, new_collection_value):
347
+ """Add a new collection name to the metadata - Chroma implementation"""
348
+ # For Chroma, we would need to update the metadata through vectorstore operations
349
+ # This is a simplified implementation - in practice, you might need more complex logic
350
+ logger.warning("add_to_collection for Chroma is not fully implemented yet")
72
351
 
73
352
 
74
353
  class VectorStoreAdapterFactory:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alita_sdk
3
- Version: 0.3.230
3
+ Version: 0.3.232
4
4
  Summary: SDK for building langchain agents using resources from Alita
5
5
  Author-email: Artem Rozumenko <artyom.rozumenko@gmail.com>, Mikalai Biazruchka <mikalai_biazruchka@epam.com>, Roman Mitusov <roman_mitusov@epam.com>, Ivan Krakhmaliuk <lifedjik@gmail.com>, Artem Dubrovskiy <ad13box@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -100,7 +100,7 @@ alita_sdk/runtime/tools/pgvector_search.py,sha256=NN2BGAnq4SsDHIhUcFZ8d_dbEOM8Qw
100
100
  alita_sdk/runtime/tools/prompt.py,sha256=nJafb_e5aOM1Rr3qGFCR-SKziU9uCsiP2okIMs9PppM,741
101
101
  alita_sdk/runtime/tools/router.py,sha256=wCvZjVkdXK9dMMeEerrgKf5M790RudH68pDortnHSz0,1517
102
102
  alita_sdk/runtime/tools/tool.py,sha256=lE1hGi6qOAXG7qxtqxarD_XMQqTghdywf261DZawwno,5631
103
- alita_sdk/runtime/tools/vectorstore.py,sha256=ItOkyorjusvoyZQcszs72FzDgo2ri9Xh3yWFhA4wdKM,38549
103
+ alita_sdk/runtime/tools/vectorstore.py,sha256=0VWmYRWgFvzGViFlhYbUk2fjkofrLlVQQg6Vnx6nxhs,33659
104
104
  alita_sdk/runtime/utils/AlitaCallback.py,sha256=E4LlSBuCHWiUq6W7IZExERHZY0qcmdjzc_rJlF2iQIw,7356
105
105
  alita_sdk/runtime/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
106
106
  alita_sdk/runtime/utils/constants.py,sha256=Xntx1b_uxUzT4clwqHA_U6K8y5bBqf_4lSQwXdcWrp4,13586
@@ -112,7 +112,7 @@ alita_sdk/runtime/utils/toolkit_runtime.py,sha256=MU63Fpxj0b5_r1IUUc0Q3-PN9VwL7r
112
112
  alita_sdk/runtime/utils/toolkit_utils.py,sha256=I9QFqnaqfVgN26LUr6s3XlBlG6y0CoHURnCzG7XcwVs,5311
113
113
  alita_sdk/runtime/utils/utils.py,sha256=CpEl3LCeLbhzQySz08lkKPm7Auac6IiLF7WB8wmArMI,589
114
114
  alita_sdk/tools/__init__.py,sha256=1AHqP2xyLjn92xVm70l9XIke6FkfHkLo5OoQVe4BuP8,10421
115
- alita_sdk/tools/elitea_base.py,sha256=22P97EmUlO-eC8DoGPiSNjHNjTv8ru0Q05qnR3U9WWs,30572
115
+ alita_sdk/tools/elitea_base.py,sha256=pxcUj_z4xDy5EQDbEkBuneDBh8QdUzevDcHkCKR35v4,30361
116
116
  alita_sdk/tools/ado/__init__.py,sha256=j4lt6MLWlpkIIVkHmAyVG3i_qQeQ3ZmL_g8BfMhVhVI,1289
117
117
  alita_sdk/tools/ado/utils.py,sha256=PTCludvaQmPLakF2EbCGy66Mro4-rjDtavVP-xcB2Wc,1252
118
118
  alita_sdk/tools/ado/repos/__init__.py,sha256=kc4ZJI3B9CDUp4q3jRSj7JZNc3fJwwMTsV40CiKO7Po,6111
@@ -214,7 +214,7 @@ alita_sdk/tools/elastic/api_wrapper.py,sha256=pl8CqQxteJAGwyOhMcld-ZgtOTFwwbv42O
214
214
  alita_sdk/tools/figma/__init__.py,sha256=281OU_aw4Y87Do09HhDSi5zL5ne9YlrsRLZQo8s1U8Q,5316
215
215
  alita_sdk/tools/figma/api_wrapper.py,sha256=Rtgt9FvR8VD0oPdYhlgvVyXLVqLTjtiOPTlwNeaV80w,20560
216
216
  alita_sdk/tools/github/__init__.py,sha256=CtU52t6-jd6JErWe3M2HF5XXWzFj9CqGmG7HBjUet6E,5348
217
- alita_sdk/tools/github/api_wrapper.py,sha256=JRhn7Cgg2j6uEwlvuQCMeISNYvRV2Yahx-v-p8HspUQ,8767
217
+ alita_sdk/tools/github/api_wrapper.py,sha256=uDwYckdnpYRJtb0uZnDkaz2udvdDLVxuCh1tSwspsiU,8411
218
218
  alita_sdk/tools/github/github_client.py,sha256=nxnSXsDul2PPbWvYZS8TmAFFmR-5ALyakNoV5LN2D4U,86617
219
219
  alita_sdk/tools/github/graphql_client_wrapper.py,sha256=d3AGjzLGH_hdQV2V8HeAX92dJ4dlnE5OXqUlCO_PBr0,71539
220
220
  alita_sdk/tools/github/schemas.py,sha256=yFsqivfjCPRk9GxFJrL8sTz6nnjFCZ0j5DIfPtGSsvA,13852
@@ -304,7 +304,7 @@ alita_sdk/tools/testrail/__init__.py,sha256=577XVaOAoXG3mDkojCsy5XCUlxCsdJf_2-_5
304
304
  alita_sdk/tools/testrail/api_wrapper.py,sha256=Aax0jspgidXYNxLIw6qTWu3dO2JOIS0ALIqsCzQuFbQ,32087
305
305
  alita_sdk/tools/utils/__init__.py,sha256=155xepXPr4OEzs2Mz5YnjXcBpxSv1X2eznRUVoPtyK0,3268
306
306
  alita_sdk/tools/utils/content_parser.py,sha256=yi1IDLreqfM41w-PnoFEvVLtSV50qpNvKshJwbDTgqs,7172
307
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py,sha256=wZ_MhVWPEgoPhKRvbPB6Qs34EPyWx0IW7ydY_GVBZFQ,3344
307
+ alita_sdk/tools/vector_adapters/VectorStoreAdapter.py,sha256=kB6KYN4IRisyNc3U4SYJ4PdOoPKH1wrRvRwvdrjZ0OQ,16850
308
308
  alita_sdk/tools/vector_adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
309
309
  alita_sdk/tools/xray/__init__.py,sha256=OYa1wveTm-lAhsJaGXMnwOrDQWl6ch--NjNLBeR63eM,4331
310
310
  alita_sdk/tools/xray/api_wrapper.py,sha256=A8PJmY2k7TowaD_vk6ZxkMnSUoZUt9A6g4TJrZfNTAw,32225
@@ -325,8 +325,8 @@ alita_sdk/tools/zephyr_scale/api_wrapper.py,sha256=JAeWf-RXohsxheUpT0iMDClc_izj-
325
325
  alita_sdk/tools/zephyr_squad/__init__.py,sha256=0AI_j27xVO5Gk5HQMFrqPTd4uvuVTpiZUicBrdfEpKg,2796
326
326
  alita_sdk/tools/zephyr_squad/api_wrapper.py,sha256=kmw_xol8YIYFplBLWTqP_VKPRhL_1ItDD0_vXTe_UuI,14906
327
327
  alita_sdk/tools/zephyr_squad/zephyr_squad_cloud_client.py,sha256=R371waHsms4sllHCbijKYs90C-9Yu0sSR3N4SUfQOgU,5066
328
- alita_sdk-0.3.230.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
329
- alita_sdk-0.3.230.dist-info/METADATA,sha256=jFOYe8oP7YbfYBFrKSoV_BtsZYIcsH2RPMmiQ-X2-tw,18896
330
- alita_sdk-0.3.230.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
331
- alita_sdk-0.3.230.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
332
- alita_sdk-0.3.230.dist-info/RECORD,,
328
+ alita_sdk-0.3.232.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
329
+ alita_sdk-0.3.232.dist-info/METADATA,sha256=HMHMoJWO6wQ3h3u5c-p_27RlppcpFUaw9BDyOL7Y9_c,18896
330
+ alita_sdk-0.3.232.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
331
+ alita_sdk-0.3.232.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
332
+ alita_sdk-0.3.232.dist-info/RECORD,,