alita-sdk 0.3.462__py3-none-any.whl → 0.3.627__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.
- alita_sdk/cli/agent/__init__.py +5 -0
- alita_sdk/cli/agent/default.py +258 -0
- alita_sdk/cli/agent_executor.py +15 -3
- alita_sdk/cli/agent_loader.py +56 -8
- alita_sdk/cli/agent_ui.py +93 -31
- alita_sdk/cli/agents.py +2274 -230
- alita_sdk/cli/callbacks.py +96 -25
- alita_sdk/cli/cli.py +10 -1
- alita_sdk/cli/config.py +162 -9
- alita_sdk/cli/context/__init__.py +30 -0
- alita_sdk/cli/context/cleanup.py +198 -0
- alita_sdk/cli/context/manager.py +731 -0
- alita_sdk/cli/context/message.py +285 -0
- alita_sdk/cli/context/strategies.py +289 -0
- alita_sdk/cli/context/token_estimation.py +127 -0
- alita_sdk/cli/input_handler.py +419 -0
- alita_sdk/cli/inventory.py +1073 -0
- alita_sdk/cli/testcases/__init__.py +94 -0
- alita_sdk/cli/testcases/data_generation.py +119 -0
- alita_sdk/cli/testcases/discovery.py +96 -0
- alita_sdk/cli/testcases/executor.py +84 -0
- alita_sdk/cli/testcases/logger.py +85 -0
- alita_sdk/cli/testcases/parser.py +172 -0
- alita_sdk/cli/testcases/prompts.py +91 -0
- alita_sdk/cli/testcases/reporting.py +125 -0
- alita_sdk/cli/testcases/setup.py +108 -0
- alita_sdk/cli/testcases/test_runner.py +282 -0
- alita_sdk/cli/testcases/utils.py +39 -0
- alita_sdk/cli/testcases/validation.py +90 -0
- alita_sdk/cli/testcases/workflow.py +196 -0
- alita_sdk/cli/toolkit.py +14 -17
- alita_sdk/cli/toolkit_loader.py +35 -5
- alita_sdk/cli/tools/__init__.py +36 -2
- alita_sdk/cli/tools/approval.py +224 -0
- alita_sdk/cli/tools/filesystem.py +910 -64
- alita_sdk/cli/tools/planning.py +389 -0
- alita_sdk/cli/tools/terminal.py +414 -0
- alita_sdk/community/__init__.py +72 -12
- alita_sdk/community/inventory/__init__.py +236 -0
- alita_sdk/community/inventory/config.py +257 -0
- alita_sdk/community/inventory/enrichment.py +2137 -0
- alita_sdk/community/inventory/extractors.py +1469 -0
- alita_sdk/community/inventory/ingestion.py +3172 -0
- alita_sdk/community/inventory/knowledge_graph.py +1457 -0
- alita_sdk/community/inventory/parsers/__init__.py +218 -0
- alita_sdk/community/inventory/parsers/base.py +295 -0
- alita_sdk/community/inventory/parsers/csharp_parser.py +907 -0
- alita_sdk/community/inventory/parsers/go_parser.py +851 -0
- alita_sdk/community/inventory/parsers/html_parser.py +389 -0
- alita_sdk/community/inventory/parsers/java_parser.py +593 -0
- alita_sdk/community/inventory/parsers/javascript_parser.py +629 -0
- alita_sdk/community/inventory/parsers/kotlin_parser.py +768 -0
- alita_sdk/community/inventory/parsers/markdown_parser.py +362 -0
- alita_sdk/community/inventory/parsers/python_parser.py +604 -0
- alita_sdk/community/inventory/parsers/rust_parser.py +858 -0
- alita_sdk/community/inventory/parsers/swift_parser.py +832 -0
- alita_sdk/community/inventory/parsers/text_parser.py +322 -0
- alita_sdk/community/inventory/parsers/yaml_parser.py +370 -0
- alita_sdk/community/inventory/patterns/__init__.py +61 -0
- alita_sdk/community/inventory/patterns/ast_adapter.py +380 -0
- alita_sdk/community/inventory/patterns/loader.py +348 -0
- alita_sdk/community/inventory/patterns/registry.py +198 -0
- alita_sdk/community/inventory/presets.py +535 -0
- alita_sdk/community/inventory/retrieval.py +1403 -0
- alita_sdk/community/inventory/toolkit.py +173 -0
- alita_sdk/community/inventory/toolkit_utils.py +176 -0
- alita_sdk/community/inventory/visualize.py +1370 -0
- alita_sdk/configurations/__init__.py +1 -1
- alita_sdk/configurations/ado.py +141 -20
- alita_sdk/configurations/bitbucket.py +0 -3
- alita_sdk/configurations/confluence.py +76 -42
- alita_sdk/configurations/figma.py +76 -0
- alita_sdk/configurations/gitlab.py +17 -5
- alita_sdk/configurations/openapi.py +329 -0
- alita_sdk/configurations/qtest.py +72 -1
- alita_sdk/configurations/report_portal.py +96 -0
- alita_sdk/configurations/sharepoint.py +148 -0
- alita_sdk/configurations/testio.py +83 -0
- alita_sdk/runtime/clients/artifact.py +3 -3
- alita_sdk/runtime/clients/client.py +353 -48
- alita_sdk/runtime/clients/sandbox_client.py +0 -21
- alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
- alita_sdk/runtime/langchain/assistant.py +123 -26
- alita_sdk/runtime/langchain/constants.py +642 -1
- alita_sdk/runtime/langchain/document_loaders/AlitaExcelLoader.py +103 -60
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLinesLoader.py +77 -0
- alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +6 -3
- alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +226 -7
- alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +5 -2
- alita_sdk/runtime/langchain/document_loaders/constants.py +12 -7
- alita_sdk/runtime/langchain/langraph_agent.py +279 -73
- alita_sdk/runtime/langchain/utils.py +82 -15
- alita_sdk/runtime/llms/preloaded.py +2 -6
- alita_sdk/runtime/skills/__init__.py +91 -0
- alita_sdk/runtime/skills/callbacks.py +498 -0
- alita_sdk/runtime/skills/discovery.py +540 -0
- alita_sdk/runtime/skills/executor.py +610 -0
- alita_sdk/runtime/skills/input_builder.py +371 -0
- alita_sdk/runtime/skills/models.py +330 -0
- alita_sdk/runtime/skills/registry.py +355 -0
- alita_sdk/runtime/skills/skill_runner.py +330 -0
- alita_sdk/runtime/toolkits/__init__.py +7 -0
- alita_sdk/runtime/toolkits/application.py +21 -9
- alita_sdk/runtime/toolkits/artifact.py +15 -5
- alita_sdk/runtime/toolkits/datasource.py +13 -6
- alita_sdk/runtime/toolkits/mcp.py +139 -251
- alita_sdk/runtime/toolkits/mcp_config.py +1048 -0
- alita_sdk/runtime/toolkits/planning.py +178 -0
- alita_sdk/runtime/toolkits/skill_router.py +238 -0
- alita_sdk/runtime/toolkits/subgraph.py +251 -6
- alita_sdk/runtime/toolkits/tools.py +238 -32
- alita_sdk/runtime/toolkits/vectorstore.py +11 -5
- alita_sdk/runtime/tools/__init__.py +3 -1
- alita_sdk/runtime/tools/application.py +20 -6
- alita_sdk/runtime/tools/artifact.py +511 -28
- alita_sdk/runtime/tools/data_analysis.py +183 -0
- alita_sdk/runtime/tools/function.py +43 -15
- alita_sdk/runtime/tools/image_generation.py +50 -44
- alita_sdk/runtime/tools/llm.py +852 -67
- alita_sdk/runtime/tools/loop.py +3 -1
- alita_sdk/runtime/tools/loop_output.py +3 -1
- alita_sdk/runtime/tools/mcp_remote_tool.py +25 -10
- alita_sdk/runtime/tools/mcp_server_tool.py +7 -6
- alita_sdk/runtime/tools/planning/__init__.py +36 -0
- alita_sdk/runtime/tools/planning/models.py +246 -0
- alita_sdk/runtime/tools/planning/wrapper.py +607 -0
- alita_sdk/runtime/tools/router.py +2 -4
- alita_sdk/runtime/tools/sandbox.py +9 -6
- alita_sdk/runtime/tools/skill_router.py +776 -0
- alita_sdk/runtime/tools/tool.py +3 -1
- alita_sdk/runtime/tools/vectorstore.py +7 -2
- alita_sdk/runtime/tools/vectorstore_base.py +51 -11
- alita_sdk/runtime/utils/AlitaCallback.py +137 -21
- alita_sdk/runtime/utils/constants.py +5 -1
- alita_sdk/runtime/utils/mcp_client.py +492 -0
- alita_sdk/runtime/utils/mcp_oauth.py +202 -5
- alita_sdk/runtime/utils/mcp_sse_client.py +36 -7
- alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
- alita_sdk/runtime/utils/serialization.py +155 -0
- alita_sdk/runtime/utils/streamlit.py +6 -10
- alita_sdk/runtime/utils/toolkit_utils.py +16 -5
- alita_sdk/runtime/utils/utils.py +36 -0
- alita_sdk/tools/__init__.py +113 -29
- alita_sdk/tools/ado/repos/__init__.py +51 -33
- alita_sdk/tools/ado/repos/repos_wrapper.py +148 -89
- alita_sdk/tools/ado/test_plan/__init__.py +25 -9
- alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +23 -1
- alita_sdk/tools/ado/utils.py +1 -18
- alita_sdk/tools/ado/wiki/__init__.py +25 -8
- alita_sdk/tools/ado/wiki/ado_wrapper.py +291 -22
- alita_sdk/tools/ado/work_item/__init__.py +26 -9
- alita_sdk/tools/ado/work_item/ado_wrapper.py +56 -3
- alita_sdk/tools/advanced_jira_mining/__init__.py +11 -8
- alita_sdk/tools/aws/delta_lake/__init__.py +13 -9
- alita_sdk/tools/aws/delta_lake/tool.py +5 -1
- alita_sdk/tools/azure_ai/search/__init__.py +11 -8
- alita_sdk/tools/azure_ai/search/api_wrapper.py +1 -1
- alita_sdk/tools/base/tool.py +5 -1
- alita_sdk/tools/base_indexer_toolkit.py +170 -45
- alita_sdk/tools/bitbucket/__init__.py +17 -12
- alita_sdk/tools/bitbucket/api_wrapper.py +59 -11
- alita_sdk/tools/bitbucket/cloud_api_wrapper.py +49 -35
- alita_sdk/tools/browser/__init__.py +5 -4
- alita_sdk/tools/carrier/__init__.py +5 -6
- alita_sdk/tools/carrier/backend_reports_tool.py +6 -6
- alita_sdk/tools/carrier/run_ui_test_tool.py +6 -6
- alita_sdk/tools/carrier/ui_reports_tool.py +5 -5
- alita_sdk/tools/chunkers/__init__.py +3 -1
- alita_sdk/tools/chunkers/code/treesitter/treesitter.py +37 -13
- alita_sdk/tools/chunkers/sematic/json_chunker.py +1 -0
- alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
- alita_sdk/tools/chunkers/universal_chunker.py +270 -0
- alita_sdk/tools/cloud/aws/__init__.py +10 -7
- alita_sdk/tools/cloud/azure/__init__.py +10 -7
- alita_sdk/tools/cloud/gcp/__init__.py +10 -7
- alita_sdk/tools/cloud/k8s/__init__.py +10 -7
- alita_sdk/tools/code/linter/__init__.py +10 -8
- alita_sdk/tools/code/loaders/codesearcher.py +3 -2
- alita_sdk/tools/code/sonar/__init__.py +10 -7
- alita_sdk/tools/code_indexer_toolkit.py +73 -23
- alita_sdk/tools/confluence/__init__.py +21 -15
- alita_sdk/tools/confluence/api_wrapper.py +78 -23
- alita_sdk/tools/confluence/loader.py +4 -2
- alita_sdk/tools/custom_open_api/__init__.py +12 -5
- alita_sdk/tools/elastic/__init__.py +11 -8
- alita_sdk/tools/elitea_base.py +493 -30
- alita_sdk/tools/figma/__init__.py +58 -11
- alita_sdk/tools/figma/api_wrapper.py +1235 -143
- alita_sdk/tools/figma/figma_client.py +73 -0
- alita_sdk/tools/figma/toon_tools.py +2748 -0
- alita_sdk/tools/github/__init__.py +13 -14
- alita_sdk/tools/github/github_client.py +224 -100
- alita_sdk/tools/github/graphql_client_wrapper.py +119 -33
- alita_sdk/tools/github/schemas.py +14 -5
- alita_sdk/tools/github/tool.py +5 -1
- alita_sdk/tools/github/tool_prompts.py +9 -22
- alita_sdk/tools/gitlab/__init__.py +15 -11
- alita_sdk/tools/gitlab/api_wrapper.py +207 -41
- alita_sdk/tools/gitlab_org/__init__.py +10 -8
- alita_sdk/tools/gitlab_org/api_wrapper.py +63 -64
- alita_sdk/tools/google/bigquery/__init__.py +13 -12
- alita_sdk/tools/google/bigquery/tool.py +5 -1
- alita_sdk/tools/google_places/__init__.py +10 -8
- alita_sdk/tools/google_places/api_wrapper.py +1 -1
- alita_sdk/tools/jira/__init__.py +17 -11
- alita_sdk/tools/jira/api_wrapper.py +91 -40
- alita_sdk/tools/keycloak/__init__.py +11 -8
- alita_sdk/tools/localgit/__init__.py +9 -3
- alita_sdk/tools/localgit/local_git.py +62 -54
- alita_sdk/tools/localgit/tool.py +5 -1
- alita_sdk/tools/memory/__init__.py +11 -3
- alita_sdk/tools/non_code_indexer_toolkit.py +1 -0
- alita_sdk/tools/ocr/__init__.py +11 -8
- alita_sdk/tools/openapi/__init__.py +490 -114
- alita_sdk/tools/openapi/api_wrapper.py +1368 -0
- alita_sdk/tools/openapi/tool.py +20 -0
- alita_sdk/tools/pandas/__init__.py +20 -12
- alita_sdk/tools/pandas/api_wrapper.py +38 -25
- alita_sdk/tools/pandas/dataframe/generator/base.py +3 -1
- alita_sdk/tools/postman/__init__.py +11 -11
- alita_sdk/tools/pptx/__init__.py +10 -9
- alita_sdk/tools/pptx/pptx_wrapper.py +1 -1
- alita_sdk/tools/qtest/__init__.py +30 -10
- alita_sdk/tools/qtest/api_wrapper.py +430 -13
- alita_sdk/tools/rally/__init__.py +10 -8
- alita_sdk/tools/rally/api_wrapper.py +1 -1
- alita_sdk/tools/report_portal/__init__.py +12 -9
- alita_sdk/tools/salesforce/__init__.py +10 -9
- alita_sdk/tools/servicenow/__init__.py +17 -14
- alita_sdk/tools/servicenow/api_wrapper.py +1 -1
- alita_sdk/tools/sharepoint/__init__.py +10 -8
- alita_sdk/tools/sharepoint/api_wrapper.py +4 -4
- alita_sdk/tools/slack/__init__.py +10 -8
- alita_sdk/tools/slack/api_wrapper.py +2 -2
- alita_sdk/tools/sql/__init__.py +11 -9
- alita_sdk/tools/testio/__init__.py +10 -8
- alita_sdk/tools/testrail/__init__.py +11 -8
- alita_sdk/tools/testrail/api_wrapper.py +1 -1
- alita_sdk/tools/utils/__init__.py +9 -4
- alita_sdk/tools/utils/content_parser.py +77 -3
- alita_sdk/tools/utils/text_operations.py +410 -0
- alita_sdk/tools/utils/tool_prompts.py +79 -0
- alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +17 -13
- alita_sdk/tools/xray/__init__.py +12 -9
- alita_sdk/tools/yagmail/__init__.py +9 -3
- alita_sdk/tools/zephyr/__init__.py +9 -7
- alita_sdk/tools/zephyr_enterprise/__init__.py +11 -8
- alita_sdk/tools/zephyr_essential/__init__.py +10 -8
- alita_sdk/tools/zephyr_essential/api_wrapper.py +30 -13
- alita_sdk/tools/zephyr_essential/client.py +2 -2
- alita_sdk/tools/zephyr_scale/__init__.py +11 -9
- alita_sdk/tools/zephyr_scale/api_wrapper.py +2 -2
- alita_sdk/tools/zephyr_squad/__init__.py +10 -8
- {alita_sdk-0.3.462.dist-info → alita_sdk-0.3.627.dist-info}/METADATA +147 -7
- alita_sdk-0.3.627.dist-info/RECORD +468 -0
- alita_sdk-0.3.627.dist-info/entry_points.txt +2 -0
- alita_sdk-0.3.462.dist-info/RECORD +0 -384
- alita_sdk-0.3.462.dist-info/entry_points.txt +0 -2
- {alita_sdk-0.3.462.dist-info → alita_sdk-0.3.627.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.462.dist-info → alita_sdk-0.3.627.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.462.dist-info → alita_sdk-0.3.627.dist-info}/top_level.txt +0 -0
alita_sdk/runtime/tools/tool.py
CHANGED
|
@@ -86,7 +86,9 @@ Answer must be JSON only extractable by JSON.LOADS."""
|
|
|
86
86
|
else:
|
|
87
87
|
input_[-1].content += self.unstructured_output
|
|
88
88
|
completion = self.client.invoke(input_, config=config)
|
|
89
|
-
|
|
89
|
+
from ..langchain.utils import extract_text_from_completion
|
|
90
|
+
content_text = extract_text_from_completion(completion)
|
|
91
|
+
result = _extract_json(content_text.strip())
|
|
90
92
|
logger.info(f"ToolNode tool params: {result}")
|
|
91
93
|
try:
|
|
92
94
|
# handler for application added as a tool
|
|
@@ -12,9 +12,11 @@ from alita_sdk.tools.vector_adapters.VectorStoreAdapter import VectorStoreAdapte
|
|
|
12
12
|
from logging import getLogger
|
|
13
13
|
|
|
14
14
|
from ..utils.logging import dispatch_custom_event
|
|
15
|
+
from ..langchain.utils import extract_text_from_completion
|
|
15
16
|
|
|
16
17
|
logger = getLogger(__name__)
|
|
17
18
|
|
|
19
|
+
|
|
18
20
|
class IndexDocumentsModel(BaseModel):
|
|
19
21
|
documents: Any = Field(description="Generator of documents to index")
|
|
20
22
|
|
|
@@ -684,8 +686,10 @@ class VectorStoreWrapper(BaseToolApiWrapper):
|
|
|
684
686
|
]
|
|
685
687
|
)
|
|
686
688
|
])
|
|
689
|
+
# Extract text content safely (handles both string and list content from thinking models)
|
|
690
|
+
search_query = extract_text_from_completion(result)
|
|
687
691
|
search_results = self.search_documents(
|
|
688
|
-
|
|
692
|
+
search_query, doctype, filter, cut_off, search_top,
|
|
689
693
|
full_text_search=full_text_search,
|
|
690
694
|
reranking_config=reranking_config,
|
|
691
695
|
extended_search=extended_search
|
|
@@ -714,7 +718,8 @@ class VectorStoreWrapper(BaseToolApiWrapper):
|
|
|
714
718
|
]
|
|
715
719
|
)
|
|
716
720
|
])
|
|
717
|
-
|
|
721
|
+
# Extract text content safely (handles both string and list content from thinking models)
|
|
722
|
+
return extract_text_from_completion(result)
|
|
718
723
|
|
|
719
724
|
def _log_data(self, message: str, tool_name: str = "index_data"):
|
|
720
725
|
"""Log data and dispatch custom event for indexing progress"""
|
|
@@ -13,9 +13,11 @@ from pydantic import BaseModel, model_validator, Field
|
|
|
13
13
|
from alita_sdk.tools.elitea_base import BaseToolApiWrapper
|
|
14
14
|
from alita_sdk.tools.vector_adapters.VectorStoreAdapter import VectorStoreAdapterFactory
|
|
15
15
|
from ...runtime.utils.utils import IndexerKeywords
|
|
16
|
+
from ...runtime.langchain.utils import extract_text_from_completion
|
|
16
17
|
|
|
17
18
|
logger = getLogger(__name__)
|
|
18
19
|
|
|
20
|
+
|
|
19
21
|
class IndexDocumentsModel(BaseModel):
|
|
20
22
|
documents: Any = Field(description="Generator of documents to index")
|
|
21
23
|
|
|
@@ -155,15 +157,45 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
155
157
|
if values.get('alita') and values.get('embedding_model'):
|
|
156
158
|
values['embeddings'] = values.get('alita').get_embeddings(values.get('embedding_model'))
|
|
157
159
|
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
# Initialize the new vector adapter
|
|
161
|
-
values['vector_adapter'] = VectorStoreAdapterFactory.create_adapter(values['vectorstore_type'])
|
|
162
|
-
logger.debug(f"Vectorstore wrapper initialized: {values}")
|
|
160
|
+
# Lazy initialization: vectorstore and vector_adapter are initialized on-demand
|
|
161
|
+
# This prevents errors when using non-index tools with broken/missing vector DB
|
|
163
162
|
return values
|
|
164
163
|
|
|
164
|
+
def _ensure_vectorstore_initialized(self):
|
|
165
|
+
"""Lazily initialize vectorstore and vector_adapter when needed for index operations."""
|
|
166
|
+
if self.vectorstore is None:
|
|
167
|
+
if not self.vectorstore_type or not self.vectorstore_params:
|
|
168
|
+
raise ToolException(
|
|
169
|
+
"Vector store is not configured. "
|
|
170
|
+
"Please ensure embedding_model and pgvector_configuration are provided."
|
|
171
|
+
)
|
|
172
|
+
|
|
173
|
+
from ..langchain.interfaces.llm_processor import get_vectorstore
|
|
174
|
+
try:
|
|
175
|
+
self.vectorstore = get_vectorstore(
|
|
176
|
+
self.vectorstore_type,
|
|
177
|
+
self.vectorstore_params,
|
|
178
|
+
embedding_func=self.embeddings
|
|
179
|
+
)
|
|
180
|
+
logger.debug(f"Vectorstore initialized: {self.vectorstore_type}")
|
|
181
|
+
except Exception as e:
|
|
182
|
+
raise ToolException(
|
|
183
|
+
f"Failed to initialize vector store: {str(e)}. "
|
|
184
|
+
"Check your vector database configuration and connection."
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
if self.vector_adapter is None:
|
|
188
|
+
try:
|
|
189
|
+
self.vector_adapter = VectorStoreAdapterFactory.create_adapter(self.vectorstore_type)
|
|
190
|
+
logger.debug(f"Vector adapter initialized: {self.vectorstore_type}")
|
|
191
|
+
except Exception as e:
|
|
192
|
+
raise ToolException(
|
|
193
|
+
f"Failed to initialize vector adapter: {str(e)}"
|
|
194
|
+
)
|
|
195
|
+
|
|
165
196
|
def _init_pg_helper(self, language='english'):
|
|
166
197
|
"""Initialize PGVector helper if needed and not already initialized"""
|
|
198
|
+
self._ensure_vectorstore_initialized()
|
|
167
199
|
if self.pg_helper is None and hasattr(self.vectorstore, 'connection_string') and hasattr(self.vectorstore, 'collection_name'):
|
|
168
200
|
try:
|
|
169
201
|
from .pgvector_search import PGVectorSearch
|
|
@@ -192,6 +224,7 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
192
224
|
Raises:
|
|
193
225
|
ToolException: When DataException occurs or other search errors
|
|
194
226
|
"""
|
|
227
|
+
self._ensure_vectorstore_initialized()
|
|
195
228
|
try:
|
|
196
229
|
return self.vectorstore.similarity_search_with_score(
|
|
197
230
|
query, filter=filter, k=k
|
|
@@ -210,19 +243,21 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
210
243
|
|
|
211
244
|
def list_collections(self) -> List[str]:
|
|
212
245
|
"""List all collections in the vectorstore."""
|
|
213
|
-
|
|
246
|
+
self._ensure_vectorstore_initialized()
|
|
214
247
|
collections = self.vector_adapter.list_collections(self)
|
|
215
248
|
if not collections:
|
|
216
249
|
return "No indexed collections"
|
|
217
250
|
return collections
|
|
218
251
|
|
|
219
252
|
def get_index_meta(self, index_name: str):
|
|
253
|
+
self._ensure_vectorstore_initialized()
|
|
220
254
|
index_metas = self.vector_adapter.get_index_meta(self, index_name)
|
|
221
255
|
if len(index_metas) > 1:
|
|
222
256
|
raise RuntimeError(f"Multiple index_meta documents found: {index_metas}")
|
|
223
257
|
return index_metas[0] if index_metas else None
|
|
224
258
|
|
|
225
259
|
def get_indexed_count(self, index_name: str) -> int:
|
|
260
|
+
self._ensure_vectorstore_initialized()
|
|
226
261
|
from sqlalchemy.orm import Session
|
|
227
262
|
from sqlalchemy import func, or_
|
|
228
263
|
|
|
@@ -237,15 +272,16 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
237
272
|
)
|
|
238
273
|
).count()
|
|
239
274
|
|
|
240
|
-
def _clean_collection(self, index_name: str = ''):
|
|
275
|
+
def _clean_collection(self, index_name: str = '', including_index_meta: bool = False):
|
|
241
276
|
"""
|
|
242
277
|
Clean the vectorstore collection by deleting all indexed data.
|
|
243
278
|
"""
|
|
279
|
+
self._ensure_vectorstore_initialized()
|
|
244
280
|
self._log_tool_event(
|
|
245
281
|
f"Cleaning collection '{self.dataset}'",
|
|
246
282
|
tool_name="_clean_collection"
|
|
247
283
|
)
|
|
248
|
-
self.vector_adapter.clean_collection(self, index_name)
|
|
284
|
+
self.vector_adapter.clean_collection(self, index_name, including_index_meta)
|
|
249
285
|
self._log_tool_event(
|
|
250
286
|
f"Collection '{self.dataset}' has been cleaned. ",
|
|
251
287
|
tool_name="_clean_collection"
|
|
@@ -259,6 +295,7 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
259
295
|
progress_step (int): Step for progress reporting, default is 20.
|
|
260
296
|
clean_index (bool): If True, clean the index before re-indexing all documents.
|
|
261
297
|
"""
|
|
298
|
+
self._ensure_vectorstore_initialized()
|
|
262
299
|
if clean_index:
|
|
263
300
|
self._clean_index(index_name)
|
|
264
301
|
|
|
@@ -268,7 +305,7 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
268
305
|
logger.info("Cleaning index before re-indexing all documents.")
|
|
269
306
|
self._log_tool_event("Cleaning index before re-indexing all documents. Previous index will be removed", tool_name="index_documents")
|
|
270
307
|
try:
|
|
271
|
-
self._clean_collection(index_name)
|
|
308
|
+
self._clean_collection(index_name, including_index_meta=False)
|
|
272
309
|
self._log_tool_event("Previous index has been removed",
|
|
273
310
|
tool_name="index_documents")
|
|
274
311
|
except Exception as e:
|
|
@@ -590,8 +627,10 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
590
627
|
]
|
|
591
628
|
)
|
|
592
629
|
])
|
|
630
|
+
# Extract text content safely (handles both string and list content from thinking models)
|
|
631
|
+
search_query = extract_text_from_completion(result)
|
|
593
632
|
search_results = self.search_documents(
|
|
594
|
-
|
|
633
|
+
search_query, doctype, filter, cut_off, search_top,
|
|
595
634
|
full_text_search=full_text_search,
|
|
596
635
|
reranking_config=reranking_config,
|
|
597
636
|
extended_search=extended_search
|
|
@@ -620,7 +659,8 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
620
659
|
]
|
|
621
660
|
)
|
|
622
661
|
])
|
|
623
|
-
|
|
662
|
+
# Extract text content safely (handles both string and list content from thinking models)
|
|
663
|
+
return extract_text_from_completion(result)
|
|
624
664
|
|
|
625
665
|
def get_available_tools(self):
|
|
626
666
|
return [
|
|
@@ -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
|
-
|
|
80
|
-
|
|
115
|
+
status_widget = self._safe_streamlit_call(
|
|
116
|
+
self.st.status,
|
|
117
|
+
f"Running {payload.get('tool_name')}...",
|
|
118
|
+
expanded=True
|
|
81
119
|
)
|
|
82
|
-
|
|
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 """
|
|
@@ -88,15 +128,51 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
|
|
|
88
128
|
|
|
89
129
|
tool_name = args[0].get("name")
|
|
90
130
|
tool_run_id = str(run_id)
|
|
131
|
+
|
|
132
|
+
# Extract metadata from tool if available (from BaseAction.metadata)
|
|
133
|
+
# Try multiple sources for metadata with toolkit_name
|
|
134
|
+
tool_meta = args[0].copy()
|
|
135
|
+
|
|
136
|
+
# Source 1: kwargs['serialized']['metadata'] - LangChain's full tool serialization
|
|
137
|
+
if 'serialized' in kwargs and 'metadata' in kwargs['serialized']:
|
|
138
|
+
tool_meta['metadata'] = kwargs['serialized']['metadata']
|
|
139
|
+
log.info(f"[METADATA] Extracted from serialized: {kwargs['serialized']['metadata']}")
|
|
140
|
+
# Source 2: Check if metadata is directly in args[0] (some LangChain versions)
|
|
141
|
+
elif 'metadata' in args[0]:
|
|
142
|
+
tool_meta['metadata'] = args[0]['metadata']
|
|
143
|
+
log.info(f"[METADATA] Extracted from args[0]: {args[0]['metadata']}")
|
|
144
|
+
else:
|
|
145
|
+
log.info(f"[METADATA] No metadata found. args[0] keys: {list(args[0].keys())}, kwargs keys: {list(kwargs.keys())}")
|
|
146
|
+
# Fallback: Try to extract toolkit_name from description
|
|
147
|
+
description = args[0].get('description', '')
|
|
148
|
+
if description:
|
|
149
|
+
import re
|
|
150
|
+
# Try pattern 1: [Toolkit: name]
|
|
151
|
+
match = re.search(r'\[Toolkit:\s*([^\]]+)\]', description)
|
|
152
|
+
if not match:
|
|
153
|
+
# Try pattern 2: Toolkit: name at start or end
|
|
154
|
+
match = re.search(r'(?:^|\n)Toolkit:\s*([^\n]+)', description)
|
|
155
|
+
if match:
|
|
156
|
+
toolkit_name = match.group(1).strip()
|
|
157
|
+
tool_meta['metadata'] = {'toolkit_name': toolkit_name}
|
|
158
|
+
log.info(f"[METADATA] Extracted toolkit_name from description: {toolkit_name}")
|
|
159
|
+
|
|
91
160
|
payload = {
|
|
92
161
|
"tool_name": tool_name,
|
|
93
162
|
"tool_run_id": tool_run_id,
|
|
94
|
-
"tool_meta":
|
|
163
|
+
"tool_meta": tool_meta,
|
|
95
164
|
"tool_inputs": kwargs.get('inputs')
|
|
96
165
|
}
|
|
97
166
|
payload = json.loads(json.dumps(payload, ensure_ascii=False, default=lambda o: str(o)))
|
|
98
|
-
|
|
99
|
-
|
|
167
|
+
|
|
168
|
+
status_widget = self._safe_streamlit_call(
|
|
169
|
+
self.st.status,
|
|
170
|
+
f"Running {tool_name}...",
|
|
171
|
+
expanded=True
|
|
172
|
+
)
|
|
173
|
+
if status_widget:
|
|
174
|
+
self.callback_state[tool_run_id] = status_widget
|
|
175
|
+
self._safe_streamlit_call(status_widget.write, f"Tool inputs: {kwargs.get('inputs')}")
|
|
100
176
|
|
|
101
177
|
def on_tool_end(self, *args, run_id: UUID, **kwargs):
|
|
102
178
|
""" Callback """
|
|
@@ -104,11 +180,16 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
|
|
|
104
180
|
log.info("on_tool_end(%s, %s)", args, kwargs)
|
|
105
181
|
tool_run_id = str(run_id)
|
|
106
182
|
tool_output = args[0]
|
|
107
|
-
if self.callback_state
|
|
108
|
-
self.callback_state[tool_run_id]
|
|
109
|
-
self.
|
|
183
|
+
if self.callback_state.get(tool_run_id):
|
|
184
|
+
status_widget = self.callback_state[tool_run_id]
|
|
185
|
+
self._safe_streamlit_call(status_widget.write, f"Tool output: {tool_output}")
|
|
186
|
+
self._safe_streamlit_call(
|
|
187
|
+
status_widget.update,
|
|
188
|
+
label=f"Completed {kwargs.get('name')}",
|
|
189
|
+
state="complete",
|
|
190
|
+
expanded=False
|
|
191
|
+
)
|
|
110
192
|
self.callback_state.pop(tool_run_id, None)
|
|
111
|
-
del self.callback_state[run_id]
|
|
112
193
|
|
|
113
194
|
def on_tool_error(self, *args, run_id: UUID, **kwargs):
|
|
114
195
|
""" Callback """
|
|
@@ -116,9 +197,19 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
|
|
|
116
197
|
log.info("on_tool_error(%s, %s)", args, kwargs)
|
|
117
198
|
tool_run_id = str(run_id)
|
|
118
199
|
tool_exception = args[0]
|
|
119
|
-
self.callback_state
|
|
120
|
-
|
|
121
|
-
|
|
200
|
+
if self.callback_state.get(tool_run_id):
|
|
201
|
+
status_widget = self.callback_state[tool_run_id]
|
|
202
|
+
self._safe_streamlit_call(
|
|
203
|
+
status_widget.write,
|
|
204
|
+
f"{traceback.format_exception(tool_exception)}"
|
|
205
|
+
)
|
|
206
|
+
self._safe_streamlit_call(
|
|
207
|
+
status_widget.update,
|
|
208
|
+
label=f"Error {kwargs.get('name')}",
|
|
209
|
+
state="error",
|
|
210
|
+
expanded=False
|
|
211
|
+
)
|
|
212
|
+
self.callback_state.pop(tool_run_id, None)
|
|
122
213
|
|
|
123
214
|
#
|
|
124
215
|
# Agent
|
|
@@ -156,8 +247,14 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
|
|
|
156
247
|
self.current_model_name = metadata.get('ls_model_name', self.current_model_name)
|
|
157
248
|
llm_run_id = str(run_id)
|
|
158
249
|
|
|
159
|
-
|
|
160
|
-
|
|
250
|
+
status_widget = self._safe_streamlit_call(
|
|
251
|
+
self.st.status,
|
|
252
|
+
f"Running LLM ...",
|
|
253
|
+
expanded=True
|
|
254
|
+
)
|
|
255
|
+
if status_widget:
|
|
256
|
+
self.callback_state[llm_run_id] = status_widget
|
|
257
|
+
self._safe_streamlit_call(status_widget.write, f"LLM inputs: {messages}")
|
|
161
258
|
|
|
162
259
|
def on_llm_start(self, *args, **kwargs):
|
|
163
260
|
""" Callback """
|
|
@@ -178,16 +275,27 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
|
|
|
178
275
|
content = None
|
|
179
276
|
if chunk:
|
|
180
277
|
content = chunk.text
|
|
181
|
-
|
|
278
|
+
|
|
279
|
+
llm_run_id = str(run_id)
|
|
280
|
+
if self.callback_state.get(llm_run_id):
|
|
281
|
+
status_widget = self.callback_state[llm_run_id]
|
|
282
|
+
self._safe_streamlit_call(status_widget.write, content)
|
|
182
283
|
|
|
183
284
|
def on_llm_error(self, *args, run_id: UUID, **kwargs):
|
|
184
285
|
""" Callback """
|
|
185
286
|
if self.debug:
|
|
186
287
|
log.error("on_llm_error(%s, %s)", args, kwargs)
|
|
187
288
|
llm_run_id = str(run_id)
|
|
188
|
-
self.callback_state
|
|
189
|
-
|
|
190
|
-
|
|
289
|
+
if self.callback_state.get(llm_run_id):
|
|
290
|
+
status_widget = self.callback_state[llm_run_id]
|
|
291
|
+
self._safe_streamlit_call(status_widget.write, f"on_llm_error({args}, {kwargs})")
|
|
292
|
+
self._safe_streamlit_call(
|
|
293
|
+
status_widget.update,
|
|
294
|
+
label=f"Error {kwargs.get('name')}",
|
|
295
|
+
state="error",
|
|
296
|
+
expanded=False
|
|
297
|
+
)
|
|
298
|
+
self.callback_state.pop(llm_run_id, None)
|
|
191
299
|
#
|
|
192
300
|
# exception = args[0]
|
|
193
301
|
# FIXME: should we emit an error here too?
|
|
@@ -205,5 +313,13 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
|
|
|
205
313
|
if self.debug:
|
|
206
314
|
log.debug("on_llm_end(%s, %s)", response, kwargs)
|
|
207
315
|
llm_run_id = str(run_id)
|
|
208
|
-
|
|
209
|
-
self.callback_state.
|
|
316
|
+
# Check if callback_state exists and is not None before accessing
|
|
317
|
+
if self.callback_state is not None and self.callback_state.get(llm_run_id):
|
|
318
|
+
status_widget = self.callback_state[llm_run_id]
|
|
319
|
+
self._safe_streamlit_call(
|
|
320
|
+
status_widget.update,
|
|
321
|
+
label=f"Completed LLM call",
|
|
322
|
+
state="complete",
|
|
323
|
+
expanded=False
|
|
324
|
+
)
|
|
325
|
+
self.callback_state.pop(llm_run_id, None)
|