alita-sdk 0.3.465__py3-none-any.whl → 0.3.497__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 alita-sdk might be problematic. Click here for more details.

Files changed (103) hide show
  1. alita_sdk/cli/agent/__init__.py +5 -0
  2. alita_sdk/cli/agent/default.py +83 -1
  3. alita_sdk/cli/agent_loader.py +22 -4
  4. alita_sdk/cli/agent_ui.py +13 -3
  5. alita_sdk/cli/agents.py +1876 -186
  6. alita_sdk/cli/callbacks.py +96 -25
  7. alita_sdk/cli/cli.py +10 -1
  8. alita_sdk/cli/config.py +151 -9
  9. alita_sdk/cli/context/__init__.py +30 -0
  10. alita_sdk/cli/context/cleanup.py +198 -0
  11. alita_sdk/cli/context/manager.py +731 -0
  12. alita_sdk/cli/context/message.py +285 -0
  13. alita_sdk/cli/context/strategies.py +289 -0
  14. alita_sdk/cli/context/token_estimation.py +127 -0
  15. alita_sdk/cli/input_handler.py +167 -4
  16. alita_sdk/cli/inventory.py +1256 -0
  17. alita_sdk/cli/toolkit.py +14 -17
  18. alita_sdk/cli/toolkit_loader.py +35 -5
  19. alita_sdk/cli/tools/__init__.py +8 -1
  20. alita_sdk/cli/tools/filesystem.py +910 -64
  21. alita_sdk/cli/tools/planning.py +143 -157
  22. alita_sdk/cli/tools/terminal.py +154 -20
  23. alita_sdk/community/__init__.py +64 -8
  24. alita_sdk/community/inventory/__init__.py +224 -0
  25. alita_sdk/community/inventory/config.py +257 -0
  26. alita_sdk/community/inventory/enrichment.py +2137 -0
  27. alita_sdk/community/inventory/extractors.py +1469 -0
  28. alita_sdk/community/inventory/ingestion.py +3172 -0
  29. alita_sdk/community/inventory/knowledge_graph.py +1457 -0
  30. alita_sdk/community/inventory/parsers/__init__.py +218 -0
  31. alita_sdk/community/inventory/parsers/base.py +295 -0
  32. alita_sdk/community/inventory/parsers/csharp_parser.py +907 -0
  33. alita_sdk/community/inventory/parsers/go_parser.py +851 -0
  34. alita_sdk/community/inventory/parsers/html_parser.py +389 -0
  35. alita_sdk/community/inventory/parsers/java_parser.py +593 -0
  36. alita_sdk/community/inventory/parsers/javascript_parser.py +629 -0
  37. alita_sdk/community/inventory/parsers/kotlin_parser.py +768 -0
  38. alita_sdk/community/inventory/parsers/markdown_parser.py +362 -0
  39. alita_sdk/community/inventory/parsers/python_parser.py +604 -0
  40. alita_sdk/community/inventory/parsers/rust_parser.py +858 -0
  41. alita_sdk/community/inventory/parsers/swift_parser.py +832 -0
  42. alita_sdk/community/inventory/parsers/text_parser.py +322 -0
  43. alita_sdk/community/inventory/parsers/yaml_parser.py +370 -0
  44. alita_sdk/community/inventory/patterns/__init__.py +61 -0
  45. alita_sdk/community/inventory/patterns/ast_adapter.py +380 -0
  46. alita_sdk/community/inventory/patterns/loader.py +348 -0
  47. alita_sdk/community/inventory/patterns/registry.py +198 -0
  48. alita_sdk/community/inventory/presets.py +535 -0
  49. alita_sdk/community/inventory/retrieval.py +1403 -0
  50. alita_sdk/community/inventory/toolkit.py +169 -0
  51. alita_sdk/community/inventory/visualize.py +1370 -0
  52. alita_sdk/configurations/bitbucket.py +0 -3
  53. alita_sdk/runtime/clients/client.py +108 -31
  54. alita_sdk/runtime/langchain/assistant.py +4 -2
  55. alita_sdk/runtime/langchain/constants.py +3 -1
  56. alita_sdk/runtime/langchain/document_loaders/AlitaExcelLoader.py +103 -60
  57. alita_sdk/runtime/langchain/document_loaders/constants.py +10 -6
  58. alita_sdk/runtime/langchain/langraph_agent.py +123 -31
  59. alita_sdk/runtime/llms/preloaded.py +2 -6
  60. alita_sdk/runtime/toolkits/__init__.py +2 -0
  61. alita_sdk/runtime/toolkits/application.py +1 -1
  62. alita_sdk/runtime/toolkits/mcp.py +107 -91
  63. alita_sdk/runtime/toolkits/planning.py +173 -0
  64. alita_sdk/runtime/toolkits/tools.py +59 -7
  65. alita_sdk/runtime/tools/artifact.py +46 -17
  66. alita_sdk/runtime/tools/function.py +2 -1
  67. alita_sdk/runtime/tools/llm.py +320 -32
  68. alita_sdk/runtime/tools/mcp_remote_tool.py +23 -7
  69. alita_sdk/runtime/tools/planning/__init__.py +36 -0
  70. alita_sdk/runtime/tools/planning/models.py +246 -0
  71. alita_sdk/runtime/tools/planning/wrapper.py +607 -0
  72. alita_sdk/runtime/tools/vectorstore_base.py +44 -9
  73. alita_sdk/runtime/utils/AlitaCallback.py +106 -20
  74. alita_sdk/runtime/utils/mcp_client.py +465 -0
  75. alita_sdk/runtime/utils/mcp_oauth.py +80 -0
  76. alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
  77. alita_sdk/runtime/utils/streamlit.py +6 -10
  78. alita_sdk/runtime/utils/toolkit_utils.py +14 -5
  79. alita_sdk/tools/__init__.py +54 -27
  80. alita_sdk/tools/ado/repos/repos_wrapper.py +1 -2
  81. alita_sdk/tools/base_indexer_toolkit.py +99 -20
  82. alita_sdk/tools/bitbucket/__init__.py +2 -2
  83. alita_sdk/tools/chunkers/__init__.py +3 -1
  84. alita_sdk/tools/chunkers/sematic/json_chunker.py +1 -0
  85. alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
  86. alita_sdk/tools/chunkers/universal_chunker.py +270 -0
  87. alita_sdk/tools/code/loaders/codesearcher.py +3 -2
  88. alita_sdk/tools/code_indexer_toolkit.py +55 -22
  89. alita_sdk/tools/confluence/api_wrapper.py +63 -14
  90. alita_sdk/tools/elitea_base.py +86 -21
  91. alita_sdk/tools/jira/__init__.py +1 -1
  92. alita_sdk/tools/jira/api_wrapper.py +91 -40
  93. alita_sdk/tools/non_code_indexer_toolkit.py +1 -0
  94. alita_sdk/tools/qtest/__init__.py +1 -1
  95. alita_sdk/tools/sharepoint/api_wrapper.py +2 -2
  96. alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +17 -13
  97. alita_sdk/tools/zephyr_essential/api_wrapper.py +12 -13
  98. {alita_sdk-0.3.465.dist-info → alita_sdk-0.3.497.dist-info}/METADATA +2 -1
  99. {alita_sdk-0.3.465.dist-info → alita_sdk-0.3.497.dist-info}/RECORD +103 -61
  100. {alita_sdk-0.3.465.dist-info → alita_sdk-0.3.497.dist-info}/WHEEL +0 -0
  101. {alita_sdk-0.3.465.dist-info → alita_sdk-0.3.497.dist-info}/entry_points.txt +0 -0
  102. {alita_sdk-0.3.465.dist-info → alita_sdk-0.3.497.dist-info}/licenses/LICENSE +0 -0
  103. {alita_sdk-0.3.465.dist-info → alita_sdk-0.3.497.dist-info}/top_level.txt +0 -0
@@ -155,15 +155,45 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
155
155
  if values.get('alita') and values.get('embedding_model'):
156
156
  values['embeddings'] = values.get('alita').get_embeddings(values.get('embedding_model'))
157
157
 
158
- if values.get('vectorstore_type') and values.get('vectorstore_params') and values.get('embedding_model'):
159
- values['vectorstore'] = get_vectorstore(values['vectorstore_type'], values['vectorstore_params'], embedding_func=values['embeddings'])
160
- # Initialize the new vector adapter
161
- values['vector_adapter'] = VectorStoreAdapterFactory.create_adapter(values['vectorstore_type'])
162
- logger.debug(f"Vectorstore wrapper initialized: {values}")
158
+ # Lazy initialization: vectorstore and vector_adapter are initialized on-demand
159
+ # This prevents errors when using non-index tools with broken/missing vector DB
163
160
  return values
164
161
 
162
+ def _ensure_vectorstore_initialized(self):
163
+ """Lazily initialize vectorstore and vector_adapter when needed for index operations."""
164
+ if self.vectorstore is None:
165
+ if not self.vectorstore_type or not self.vectorstore_params:
166
+ raise ToolException(
167
+ "Vector store is not configured. "
168
+ "Please ensure embedding_model and pgvector_configuration are provided."
169
+ )
170
+
171
+ from ..langchain.interfaces.llm_processor import get_vectorstore
172
+ try:
173
+ self.vectorstore = get_vectorstore(
174
+ self.vectorstore_type,
175
+ self.vectorstore_params,
176
+ embedding_func=self.embeddings
177
+ )
178
+ logger.debug(f"Vectorstore initialized: {self.vectorstore_type}")
179
+ except Exception as e:
180
+ raise ToolException(
181
+ f"Failed to initialize vector store: {str(e)}. "
182
+ "Check your vector database configuration and connection."
183
+ )
184
+
185
+ if self.vector_adapter is None:
186
+ try:
187
+ self.vector_adapter = VectorStoreAdapterFactory.create_adapter(self.vectorstore_type)
188
+ logger.debug(f"Vector adapter initialized: {self.vectorstore_type}")
189
+ except Exception as e:
190
+ raise ToolException(
191
+ f"Failed to initialize vector adapter: {str(e)}"
192
+ )
193
+
165
194
  def _init_pg_helper(self, language='english'):
166
195
  """Initialize PGVector helper if needed and not already initialized"""
196
+ self._ensure_vectorstore_initialized()
167
197
  if self.pg_helper is None and hasattr(self.vectorstore, 'connection_string') and hasattr(self.vectorstore, 'collection_name'):
168
198
  try:
169
199
  from .pgvector_search import PGVectorSearch
@@ -192,6 +222,7 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
192
222
  Raises:
193
223
  ToolException: When DataException occurs or other search errors
194
224
  """
225
+ self._ensure_vectorstore_initialized()
195
226
  try:
196
227
  return self.vectorstore.similarity_search_with_score(
197
228
  query, filter=filter, k=k
@@ -210,19 +241,21 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
210
241
 
211
242
  def list_collections(self) -> List[str]:
212
243
  """List all collections in the vectorstore."""
213
-
244
+ self._ensure_vectorstore_initialized()
214
245
  collections = self.vector_adapter.list_collections(self)
215
246
  if not collections:
216
247
  return "No indexed collections"
217
248
  return collections
218
249
 
219
250
  def get_index_meta(self, index_name: str):
251
+ self._ensure_vectorstore_initialized()
220
252
  index_metas = self.vector_adapter.get_index_meta(self, index_name)
221
253
  if len(index_metas) > 1:
222
254
  raise RuntimeError(f"Multiple index_meta documents found: {index_metas}")
223
255
  return index_metas[0] if index_metas else None
224
256
 
225
257
  def get_indexed_count(self, index_name: str) -> int:
258
+ self._ensure_vectorstore_initialized()
226
259
  from sqlalchemy.orm import Session
227
260
  from sqlalchemy import func, or_
228
261
 
@@ -237,15 +270,16 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
237
270
  )
238
271
  ).count()
239
272
 
240
- def _clean_collection(self, index_name: str = ''):
273
+ def _clean_collection(self, index_name: str = '', including_index_meta: bool = False):
241
274
  """
242
275
  Clean the vectorstore collection by deleting all indexed data.
243
276
  """
277
+ self._ensure_vectorstore_initialized()
244
278
  self._log_tool_event(
245
279
  f"Cleaning collection '{self.dataset}'",
246
280
  tool_name="_clean_collection"
247
281
  )
248
- self.vector_adapter.clean_collection(self, index_name)
282
+ self.vector_adapter.clean_collection(self, index_name, including_index_meta)
249
283
  self._log_tool_event(
250
284
  f"Collection '{self.dataset}' has been cleaned. ",
251
285
  tool_name="_clean_collection"
@@ -259,6 +293,7 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
259
293
  progress_step (int): Step for progress reporting, default is 20.
260
294
  clean_index (bool): If True, clean the index before re-indexing all documents.
261
295
  """
296
+ self._ensure_vectorstore_initialized()
262
297
  if clean_index:
263
298
  self._clean_index(index_name)
264
299
 
@@ -268,7 +303,7 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
268
303
  logger.info("Cleaning index before re-indexing all documents.")
269
304
  self._log_tool_event("Cleaning index before re-indexing all documents. Previous index will be removed", tool_name="index_documents")
270
305
  try:
271
- self._clean_collection(index_name)
306
+ self._clean_collection(index_name, including_index_meta=False)
272
307
  self._log_tool_event("Previous index has been removed",
273
308
  tool_name="index_documents")
274
309
  except Exception as e:
@@ -23,9 +23,45 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
23
23
  self.tokens_out = 0
24
24
  self.pending_llm_requests = defaultdict(int)
25
25
  self.current_model_name = 'gpt-4'
26
+ self._event_queue = [] # Queue for events when context is unavailable
26
27
  #
27
28
  super().__init__()
28
29
 
30
+ def _has_streamlit_context(self) -> bool:
31
+ """Check if Streamlit context is available in the current thread."""
32
+ try:
33
+ # Try to import streamlit runtime context checker
34
+ from streamlit.runtime.scriptrunner import get_script_run_ctx
35
+ ctx = get_script_run_ctx()
36
+ return ctx is not None
37
+ except (ImportError, Exception) as e:
38
+ if self.debug:
39
+ log.debug(f"Streamlit context check failed: {e}")
40
+ return False
41
+
42
+ def _safe_streamlit_call(self, func, *args, **kwargs):
43
+ """Safely execute a Streamlit UI operation, handling missing context gracefully."""
44
+ if not self._has_streamlit_context():
45
+ func_name = getattr(func, '__name__', str(func))
46
+ if self.debug:
47
+ log.warning(f"Streamlit context not available for {func_name}, queueing event")
48
+ # Store the event for potential replay when context is available
49
+ self._event_queue.append({
50
+ 'func': func_name,
51
+ 'args': args,
52
+ 'kwargs': kwargs,
53
+ 'timestamp': datetime.now(tz=timezone.utc)
54
+ })
55
+ return None
56
+
57
+ try:
58
+ return func(*args, **kwargs)
59
+ except Exception as e:
60
+ func_name = getattr(func, '__name__', str(func))
61
+ # Handle any Streamlit-specific exceptions gracefully
62
+ log.warning(f"Streamlit operation {func_name} failed: {e}")
63
+ return None
64
+
29
65
  #
30
66
  # Chain
31
67
  #
@@ -76,10 +112,14 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
76
112
  json.dumps(payload, ensure_ascii=False, default=lambda o: str(o))
77
113
  )
78
114
 
79
- self.callback_state[str(run_id)] = self.st.status(
80
- f"Running {payload.get('tool_name')}...", expanded=True
115
+ status_widget = self._safe_streamlit_call(
116
+ self.st.status,
117
+ f"Running {payload.get('tool_name')}...",
118
+ expanded=True
81
119
  )
82
- self.callback_state[str(run_id)].write(f"Tool inputs: {payload}")
120
+ if status_widget:
121
+ self.callback_state[str(run_id)] = status_widget
122
+ self._safe_streamlit_call(status_widget.write, f"Tool inputs: {payload}")
83
123
 
84
124
  def on_tool_start(self, *args, run_id: UUID, **kwargs):
85
125
  """ Callback """
@@ -95,8 +135,15 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
95
135
  "tool_inputs": kwargs.get('inputs')
96
136
  }
97
137
  payload = json.loads(json.dumps(payload, ensure_ascii=False, default=lambda o: str(o)))
98
- self.callback_state[tool_run_id] = self.st.status(f"Running {tool_name}...", expanded=True)
99
- self.callback_state[tool_run_id].write(f"Tool inputs: {kwargs.get('inputs')}")
138
+
139
+ status_widget = self._safe_streamlit_call(
140
+ self.st.status,
141
+ f"Running {tool_name}...",
142
+ expanded=True
143
+ )
144
+ if status_widget:
145
+ self.callback_state[tool_run_id] = status_widget
146
+ self._safe_streamlit_call(status_widget.write, f"Tool inputs: {kwargs.get('inputs')}")
100
147
 
101
148
  def on_tool_end(self, *args, run_id: UUID, **kwargs):
102
149
  """ Callback """
@@ -104,11 +151,16 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
104
151
  log.info("on_tool_end(%s, %s)", args, kwargs)
105
152
  tool_run_id = str(run_id)
106
153
  tool_output = args[0]
107
- if self.callback_state[tool_run_id]:
108
- self.callback_state[tool_run_id].write(f"Tool output: {tool_output}")
109
- self.callback_state[tool_run_id].update(label=f"Completed {kwargs.get('name')}", state="complete", expanded=False)
154
+ if self.callback_state.get(tool_run_id):
155
+ status_widget = self.callback_state[tool_run_id]
156
+ self._safe_streamlit_call(status_widget.write, f"Tool output: {tool_output}")
157
+ self._safe_streamlit_call(
158
+ status_widget.update,
159
+ label=f"Completed {kwargs.get('name')}",
160
+ state="complete",
161
+ expanded=False
162
+ )
110
163
  self.callback_state.pop(tool_run_id, None)
111
- del self.callback_state[run_id]
112
164
 
113
165
  def on_tool_error(self, *args, run_id: UUID, **kwargs):
114
166
  """ Callback """
@@ -116,9 +168,19 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
116
168
  log.info("on_tool_error(%s, %s)", args, kwargs)
117
169
  tool_run_id = str(run_id)
118
170
  tool_exception = args[0]
119
- self.callback_state[tool_run_id].write(f"{traceback.format_exception(tool_exception)}")
120
- self.callback_state[tool_run_id].update(label=f"Error {kwargs.get('name')}", state="error", expanded=False)
121
- self.callback_state.pop(tool_run_id, None)
171
+ if self.callback_state.get(tool_run_id):
172
+ status_widget = self.callback_state[tool_run_id]
173
+ self._safe_streamlit_call(
174
+ status_widget.write,
175
+ f"{traceback.format_exception(tool_exception)}"
176
+ )
177
+ self._safe_streamlit_call(
178
+ status_widget.update,
179
+ label=f"Error {kwargs.get('name')}",
180
+ state="error",
181
+ expanded=False
182
+ )
183
+ self.callback_state.pop(tool_run_id, None)
122
184
 
123
185
  #
124
186
  # Agent
@@ -156,8 +218,14 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
156
218
  self.current_model_name = metadata.get('ls_model_name', self.current_model_name)
157
219
  llm_run_id = str(run_id)
158
220
 
159
- self.callback_state[llm_run_id] = self.st.status(f"Running LLM ...", expanded=True)
160
- self.callback_state[llm_run_id].write(f"LLM inputs: {messages}")
221
+ status_widget = self._safe_streamlit_call(
222
+ self.st.status,
223
+ f"Running LLM ...",
224
+ expanded=True
225
+ )
226
+ if status_widget:
227
+ self.callback_state[llm_run_id] = status_widget
228
+ self._safe_streamlit_call(status_widget.write, f"LLM inputs: {messages}")
161
229
 
162
230
  def on_llm_start(self, *args, **kwargs):
163
231
  """ Callback """
@@ -178,16 +246,27 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
178
246
  content = None
179
247
  if chunk:
180
248
  content = chunk.text
181
- self.callback_state[str(run_id)].write(content)
249
+
250
+ llm_run_id = str(run_id)
251
+ if self.callback_state.get(llm_run_id):
252
+ status_widget = self.callback_state[llm_run_id]
253
+ self._safe_streamlit_call(status_widget.write, content)
182
254
 
183
255
  def on_llm_error(self, *args, run_id: UUID, **kwargs):
184
256
  """ Callback """
185
257
  if self.debug:
186
258
  log.error("on_llm_error(%s, %s)", args, kwargs)
187
259
  llm_run_id = str(run_id)
188
- self.callback_state[llm_run_id].write(f"on_llm_error({args}, {kwargs})")
189
- self.callback_state[llm_run_id].update(label=f"Error {kwargs.get('name')}", state="error", expanded=False)
190
- self.callback_state.pop(llm_run_id, None)
260
+ if self.callback_state.get(llm_run_id):
261
+ status_widget = self.callback_state[llm_run_id]
262
+ self._safe_streamlit_call(status_widget.write, f"on_llm_error({args}, {kwargs})")
263
+ self._safe_streamlit_call(
264
+ status_widget.update,
265
+ label=f"Error {kwargs.get('name')}",
266
+ state="error",
267
+ expanded=False
268
+ )
269
+ self.callback_state.pop(llm_run_id, None)
191
270
  #
192
271
  # exception = args[0]
193
272
  # FIXME: should we emit an error here too?
@@ -205,5 +284,12 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
205
284
  if self.debug:
206
285
  log.debug("on_llm_end(%s, %s)", response, kwargs)
207
286
  llm_run_id = str(run_id)
208
- self.callback_state[llm_run_id].update(label=f"Completed LLM call", state="complete", expanded=False)
209
- self.callback_state.pop(llm_run_id, None)
287
+ if self.callback_state.get(llm_run_id):
288
+ status_widget = self.callback_state[llm_run_id]
289
+ self._safe_streamlit_call(
290
+ status_widget.update,
291
+ label=f"Completed LLM call",
292
+ state="complete",
293
+ expanded=False
294
+ )
295
+ self.callback_state.pop(llm_run_id, None)