alita-sdk 0.3.379__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/__init__.py +10 -0
- alita_sdk/cli/__main__.py +17 -0
- alita_sdk/cli/agent/__init__.py +5 -0
- alita_sdk/cli/agent/default.py +258 -0
- alita_sdk/cli/agent_executor.py +156 -0
- alita_sdk/cli/agent_loader.py +245 -0
- alita_sdk/cli/agent_ui.py +228 -0
- alita_sdk/cli/agents.py +3113 -0
- alita_sdk/cli/callbacks.py +647 -0
- alita_sdk/cli/cli.py +168 -0
- alita_sdk/cli/config.py +306 -0
- 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/formatting.py +182 -0
- alita_sdk/cli/input_handler.py +419 -0
- alita_sdk/cli/inventory.py +1073 -0
- alita_sdk/cli/mcp_loader.py +315 -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 +327 -0
- alita_sdk/cli/toolkit_loader.py +85 -0
- alita_sdk/cli/tools/__init__.py +43 -0
- alita_sdk/cli/tools/approval.py +224 -0
- alita_sdk/cli/tools/filesystem.py +1751 -0
- 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 +94 -2
- alita_sdk/configurations/confluence.py +130 -1
- alita_sdk/configurations/figma.py +76 -0
- alita_sdk/configurations/gitlab.py +91 -0
- alita_sdk/configurations/jira.py +103 -0
- 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/configurations/testrail.py +88 -0
- alita_sdk/configurations/xray.py +93 -0
- alita_sdk/configurations/zephyr_enterprise.py +93 -0
- alita_sdk/configurations/zephyr_essential.py +75 -0
- alita_sdk/runtime/clients/artifact.py +3 -3
- alita_sdk/runtime/clients/client.py +388 -46
- alita_sdk/runtime/clients/mcp_discovery.py +342 -0
- alita_sdk/runtime/clients/mcp_manager.py +262 -0
- alita_sdk/runtime/clients/sandbox_client.py +8 -21
- alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
- alita_sdk/runtime/langchain/assistant.py +157 -39
- alita_sdk/runtime/langchain/constants.py +647 -1
- alita_sdk/runtime/langchain/document_loaders/AlitaDocxMammothLoader.py +315 -3
- 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 +10 -4
- 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 +40 -19
- alita_sdk/runtime/langchain/langraph_agent.py +405 -84
- alita_sdk/runtime/langchain/utils.py +106 -7
- alita_sdk/runtime/llms/preloaded.py +2 -6
- alita_sdk/runtime/models/mcp_models.py +61 -0
- 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 +31 -0
- alita_sdk/runtime/toolkits/application.py +29 -10
- alita_sdk/runtime/toolkits/artifact.py +20 -11
- alita_sdk/runtime/toolkits/datasource.py +13 -6
- alita_sdk/runtime/toolkits/mcp.py +783 -0
- 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 +356 -69
- alita_sdk/runtime/toolkits/vectorstore.py +11 -5
- alita_sdk/runtime/tools/__init__.py +10 -3
- alita_sdk/runtime/tools/application.py +27 -6
- alita_sdk/runtime/tools/artifact.py +511 -28
- alita_sdk/runtime/tools/data_analysis.py +183 -0
- alita_sdk/runtime/tools/function.py +67 -35
- alita_sdk/runtime/tools/graph.py +10 -4
- alita_sdk/runtime/tools/image_generation.py +148 -46
- alita_sdk/runtime/tools/llm.py +1003 -128
- alita_sdk/runtime/tools/loop.py +3 -1
- alita_sdk/runtime/tools/loop_output.py +3 -1
- alita_sdk/runtime/tools/mcp_inspect_tool.py +284 -0
- alita_sdk/runtime/tools/mcp_remote_tool.py +181 -0
- alita_sdk/runtime/tools/mcp_server_tool.py +8 -5
- 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 +65 -48
- alita_sdk/runtime/tools/skill_router.py +776 -0
- alita_sdk/runtime/tools/tool.py +3 -1
- alita_sdk/runtime/tools/vectorstore.py +9 -3
- alita_sdk/runtime/tools/vectorstore_base.py +70 -14
- 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 +361 -0
- alita_sdk/runtime/utils/mcp_sse_client.py +434 -0
- alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
- alita_sdk/runtime/utils/serialization.py +155 -0
- alita_sdk/runtime/utils/streamlit.py +40 -13
- alita_sdk/runtime/utils/toolkit_utils.py +30 -9
- alita_sdk/runtime/utils/utils.py +36 -0
- alita_sdk/tools/__init__.py +134 -35
- alita_sdk/tools/ado/repos/__init__.py +51 -32
- 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 -12
- alita_sdk/tools/ado/wiki/ado_wrapper.py +291 -22
- alita_sdk/tools/ado/work_item/__init__.py +26 -13
- alita_sdk/tools/ado/work_item/ado_wrapper.py +73 -11
- 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 +271 -84
- alita_sdk/tools/bitbucket/__init__.py +17 -11
- 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/sematic/proposal_chunker.py +1 -1
- 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 +11 -8
- alita_sdk/tools/code_indexer_toolkit.py +82 -22
- alita_sdk/tools/confluence/__init__.py +22 -16
- alita_sdk/tools/confluence/api_wrapper.py +107 -30
- alita_sdk/tools/confluence/loader.py +14 -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 +14 -15
- 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 +16 -11
- alita_sdk/tools/gitlab/api_wrapper.py +218 -48
- alita_sdk/tools/gitlab_org/__init__.py +10 -9
- 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 +11 -8
- alita_sdk/tools/google_places/api_wrapper.py +1 -1
- alita_sdk/tools/jira/__init__.py +17 -10
- alita_sdk/tools/jira/api_wrapper.py +92 -41
- 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 +12 -4
- alita_sdk/tools/non_code_indexer_toolkit.py +1 -0
- alita_sdk/tools/ocr/__init__.py +11 -8
- alita_sdk/tools/openapi/__init__.py +491 -106
- 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 +10 -9
- alita_sdk/tools/pptx/__init__.py +11 -10
- alita_sdk/tools/pptx/pptx_wrapper.py +1 -1
- alita_sdk/tools/qtest/__init__.py +31 -11
- alita_sdk/tools/qtest/api_wrapper.py +2135 -86
- alita_sdk/tools/rally/__init__.py +10 -9
- alita_sdk/tools/rally/api_wrapper.py +1 -1
- alita_sdk/tools/report_portal/__init__.py +12 -8
- alita_sdk/tools/salesforce/__init__.py +10 -8
- alita_sdk/tools/servicenow/__init__.py +17 -15
- alita_sdk/tools/servicenow/api_wrapper.py +1 -1
- alita_sdk/tools/sharepoint/__init__.py +10 -7
- alita_sdk/tools/sharepoint/api_wrapper.py +129 -38
- alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
- alita_sdk/tools/sharepoint/utils.py +8 -2
- alita_sdk/tools/slack/__init__.py +10 -7
- alita_sdk/tools/slack/api_wrapper.py +2 -2
- alita_sdk/tools/sql/__init__.py +12 -9
- alita_sdk/tools/testio/__init__.py +10 -7
- alita_sdk/tools/testrail/__init__.py +11 -10
- alita_sdk/tools/testrail/api_wrapper.py +1 -1
- alita_sdk/tools/utils/__init__.py +9 -4
- alita_sdk/tools/utils/content_parser.py +103 -18
- 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 +30 -13
- alita_sdk/tools/xray/__init__.py +13 -9
- alita_sdk/tools/yagmail/__init__.py +9 -3
- alita_sdk/tools/zephyr/__init__.py +10 -7
- alita_sdk/tools/zephyr_enterprise/__init__.py +11 -7
- alita_sdk/tools/zephyr_essential/__init__.py +10 -7
- 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 -8
- alita_sdk/tools/zephyr_scale/api_wrapper.py +2 -2
- alita_sdk/tools/zephyr_squad/__init__.py +10 -7
- {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/METADATA +154 -8
- 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.379.dist-info/RECORD +0 -360
- {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/WHEEL +0 -0
- {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.379.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
|
|
|
@@ -414,7 +416,8 @@ class VectorStoreWrapper(BaseToolApiWrapper):
|
|
|
414
416
|
return {"status": "error", "message": f"Error: {format_exc()}"}
|
|
415
417
|
if _documents:
|
|
416
418
|
add_documents(vectorstore=self.vectorstore, documents=_documents)
|
|
417
|
-
return {"status": "ok", "message": f"successfully indexed {documents_count} documents"
|
|
419
|
+
return {"status": "ok", "message": f"successfully indexed {documents_count} documents" if documents_count > 0
|
|
420
|
+
else "No new documents to index."}
|
|
418
421
|
|
|
419
422
|
def search_documents(self, query:str, doctype: str = 'code',
|
|
420
423
|
filter:dict|str={}, cut_off: float=0.5,
|
|
@@ -683,8 +686,10 @@ class VectorStoreWrapper(BaseToolApiWrapper):
|
|
|
683
686
|
]
|
|
684
687
|
)
|
|
685
688
|
])
|
|
689
|
+
# Extract text content safely (handles both string and list content from thinking models)
|
|
690
|
+
search_query = extract_text_from_completion(result)
|
|
686
691
|
search_results = self.search_documents(
|
|
687
|
-
|
|
692
|
+
search_query, doctype, filter, cut_off, search_top,
|
|
688
693
|
full_text_search=full_text_search,
|
|
689
694
|
reranking_config=reranking_config,
|
|
690
695
|
extended_search=extended_search
|
|
@@ -713,7 +718,8 @@ class VectorStoreWrapper(BaseToolApiWrapper):
|
|
|
713
718
|
]
|
|
714
719
|
)
|
|
715
720
|
])
|
|
716
|
-
|
|
721
|
+
# Extract text content safely (handles both string and list content from thinking models)
|
|
722
|
+
return extract_text_from_completion(result)
|
|
717
723
|
|
|
718
724
|
def _log_data(self, message: str, tool_name: str = "index_data"):
|
|
719
725
|
"""Log data and dispatch custom event for indexing progress"""
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import json
|
|
2
|
-
import math
|
|
3
2
|
from collections import OrderedDict
|
|
4
3
|
from logging import getLogger
|
|
5
4
|
from typing import Any, Optional, List, Dict, Generator
|
|
6
5
|
|
|
6
|
+
import math
|
|
7
7
|
from langchain_core.documents import Document
|
|
8
8
|
from langchain_core.messages import HumanMessage
|
|
9
9
|
from langchain_core.tools import ToolException
|
|
@@ -12,10 +12,12 @@ from pydantic import BaseModel, model_validator, Field
|
|
|
12
12
|
|
|
13
13
|
from alita_sdk.tools.elitea_base import BaseToolApiWrapper
|
|
14
14
|
from alita_sdk.tools.vector_adapters.VectorStoreAdapter import VectorStoreAdapterFactory
|
|
15
|
-
from
|
|
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,27 +243,45 @@ 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
|
-
def
|
|
259
|
+
def get_indexed_count(self, index_name: str) -> int:
|
|
260
|
+
self._ensure_vectorstore_initialized()
|
|
261
|
+
from sqlalchemy.orm import Session
|
|
262
|
+
from sqlalchemy import func, or_
|
|
263
|
+
|
|
264
|
+
with Session(self.vectorstore.session_maker.bind) as session:
|
|
265
|
+
return session.query(
|
|
266
|
+
self.vectorstore.EmbeddingStore.id,
|
|
267
|
+
).filter(
|
|
268
|
+
func.jsonb_extract_path_text(self.vectorstore.EmbeddingStore.cmetadata, 'collection') == index_name,
|
|
269
|
+
or_(
|
|
270
|
+
func.jsonb_extract_path_text(self.vectorstore.EmbeddingStore.cmetadata, 'type').is_(None),
|
|
271
|
+
func.jsonb_extract_path_text(self.vectorstore.EmbeddingStore.cmetadata, 'type') != IndexerKeywords.INDEX_META_TYPE.value
|
|
272
|
+
)
|
|
273
|
+
).count()
|
|
274
|
+
|
|
275
|
+
def _clean_collection(self, index_name: str = '', including_index_meta: bool = False):
|
|
226
276
|
"""
|
|
227
277
|
Clean the vectorstore collection by deleting all indexed data.
|
|
228
278
|
"""
|
|
279
|
+
self._ensure_vectorstore_initialized()
|
|
229
280
|
self._log_tool_event(
|
|
230
281
|
f"Cleaning collection '{self.dataset}'",
|
|
231
282
|
tool_name="_clean_collection"
|
|
232
283
|
)
|
|
233
|
-
self.vector_adapter.clean_collection(self, index_name)
|
|
284
|
+
self.vector_adapter.clean_collection(self, index_name, including_index_meta)
|
|
234
285
|
self._log_tool_event(
|
|
235
286
|
f"Collection '{self.dataset}' has been cleaned. ",
|
|
236
287
|
tool_name="_clean_collection"
|
|
@@ -244,6 +295,7 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
244
295
|
progress_step (int): Step for progress reporting, default is 20.
|
|
245
296
|
clean_index (bool): If True, clean the index before re-indexing all documents.
|
|
246
297
|
"""
|
|
298
|
+
self._ensure_vectorstore_initialized()
|
|
247
299
|
if clean_index:
|
|
248
300
|
self._clean_index(index_name)
|
|
249
301
|
|
|
@@ -253,7 +305,7 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
253
305
|
logger.info("Cleaning index before re-indexing all documents.")
|
|
254
306
|
self._log_tool_event("Cleaning index before re-indexing all documents. Previous index will be removed", tool_name="index_documents")
|
|
255
307
|
try:
|
|
256
|
-
self._clean_collection(index_name)
|
|
308
|
+
self._clean_collection(index_name, including_index_meta=False)
|
|
257
309
|
self._log_tool_event("Previous index has been removed",
|
|
258
310
|
tool_name="index_documents")
|
|
259
311
|
except Exception as e:
|
|
@@ -308,7 +360,8 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
308
360
|
return {"status": "error", "message": f"Error: {format_exc()}"}
|
|
309
361
|
if _documents:
|
|
310
362
|
add_documents(vectorstore=self.vectorstore, documents=_documents)
|
|
311
|
-
return {"status": "ok", "message": f"successfully indexed {documents_count} documents"
|
|
363
|
+
return {"status": "ok", "message": f"successfully indexed {documents_count} documents" if documents_count > 0
|
|
364
|
+
else "no documents to index"}
|
|
312
365
|
|
|
313
366
|
def search_documents(self, query:str, doctype: str = 'code',
|
|
314
367
|
filter:dict|str={}, cut_off: float=0.5,
|
|
@@ -574,8 +627,10 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
574
627
|
]
|
|
575
628
|
)
|
|
576
629
|
])
|
|
630
|
+
# Extract text content safely (handles both string and list content from thinking models)
|
|
631
|
+
search_query = extract_text_from_completion(result)
|
|
577
632
|
search_results = self.search_documents(
|
|
578
|
-
|
|
633
|
+
search_query, doctype, filter, cut_off, search_top,
|
|
579
634
|
full_text_search=full_text_search,
|
|
580
635
|
reranking_config=reranking_config,
|
|
581
636
|
extended_search=extended_search
|
|
@@ -604,7 +659,8 @@ class VectorStoreWrapperBase(BaseToolApiWrapper):
|
|
|
604
659
|
]
|
|
605
660
|
)
|
|
606
661
|
])
|
|
607
|
-
|
|
662
|
+
# Extract text content safely (handles both string and list content from thinking models)
|
|
663
|
+
return extract_text_from_completion(result)
|
|
608
664
|
|
|
609
665
|
def get_available_tools(self):
|
|
610
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)
|