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
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"""
|
|
2
|
+
PlanningToolkit - Runtime toolkit for agent plan management.
|
|
3
|
+
|
|
4
|
+
Provides tools for creating, tracking, and completing multi-step execution plans.
|
|
5
|
+
Supports two storage backends:
|
|
6
|
+
1. PostgreSQL - when pgvector_configuration with connection_string is provided
|
|
7
|
+
2. Filesystem - when no connection string (local CLI usage)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from typing import ClassVar, List, Any, Literal, Optional, Callable
|
|
11
|
+
|
|
12
|
+
from langchain_community.agent_toolkits.base import BaseToolkit
|
|
13
|
+
from langchain_core.tools import BaseTool
|
|
14
|
+
from pydantic import create_model, BaseModel, ConfigDict, Field
|
|
15
|
+
from pydantic.fields import FieldInfo
|
|
16
|
+
|
|
17
|
+
from ..tools.planning import PlanningWrapper
|
|
18
|
+
from ...tools.base.tool import BaseAction
|
|
19
|
+
from ...tools.utils import clean_string, get_max_toolkit_length
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class PlanningToolkit(BaseToolkit):
|
|
23
|
+
"""
|
|
24
|
+
Toolkit for agent plan management.
|
|
25
|
+
|
|
26
|
+
Provides tools for creating, updating, and tracking execution plans.
|
|
27
|
+
Supports PostgreSQL (production) and filesystem (local) storage backends.
|
|
28
|
+
Plans are scoped by conversation_id.
|
|
29
|
+
"""
|
|
30
|
+
tools: List[BaseTool] = []
|
|
31
|
+
_toolkit_max_length: ClassVar[int] = 50 # Use ClassVar to avoid Pydantic treating it as field
|
|
32
|
+
|
|
33
|
+
@staticmethod
|
|
34
|
+
def toolkit_config_schema() -> BaseModel:
|
|
35
|
+
"""
|
|
36
|
+
Returns the configuration schema for the Planning toolkit.
|
|
37
|
+
|
|
38
|
+
Used by the UI to generate the toolkit configuration form.
|
|
39
|
+
"""
|
|
40
|
+
# Define available tools
|
|
41
|
+
selected_tools = {
|
|
42
|
+
'update_plan': {
|
|
43
|
+
'title': 'UpdatePlanInput',
|
|
44
|
+
'type': 'object',
|
|
45
|
+
'properties': {
|
|
46
|
+
'title': {'type': 'string', 'description': "Title for the plan"},
|
|
47
|
+
'steps': {'type': 'array', 'items': {'type': 'string'}, 'description': "List of step descriptions"},
|
|
48
|
+
'conversation_id': {'type': 'string', 'description': "Conversation ID (auto-injected)"}
|
|
49
|
+
},
|
|
50
|
+
'required': ['title', 'steps', 'conversation_id']
|
|
51
|
+
},
|
|
52
|
+
'complete_step': {
|
|
53
|
+
'title': 'CompleteStepInput',
|
|
54
|
+
'type': 'object',
|
|
55
|
+
'properties': {
|
|
56
|
+
'step_number': {'type': 'integer', 'description': "Step number to complete (1-indexed)"},
|
|
57
|
+
'conversation_id': {'type': 'string', 'description': "Conversation ID (auto-injected)"}
|
|
58
|
+
},
|
|
59
|
+
'required': ['step_number', 'conversation_id']
|
|
60
|
+
},
|
|
61
|
+
'get_plan_status': {
|
|
62
|
+
'title': 'GetPlanStatusInput',
|
|
63
|
+
'type': 'object',
|
|
64
|
+
'properties': {
|
|
65
|
+
'conversation_id': {'type': 'string', 'description': "Conversation ID (auto-injected)"}
|
|
66
|
+
},
|
|
67
|
+
'required': ['conversation_id']
|
|
68
|
+
},
|
|
69
|
+
'delete_plan': {
|
|
70
|
+
'title': 'DeletePlanInput',
|
|
71
|
+
'type': 'object',
|
|
72
|
+
'properties': {
|
|
73
|
+
'conversation_id': {'type': 'string', 'description': "Conversation ID (auto-injected)"}
|
|
74
|
+
},
|
|
75
|
+
'required': ['conversation_id']
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
PlanningToolkit._toolkit_max_length = get_max_toolkit_length(selected_tools)
|
|
80
|
+
|
|
81
|
+
return create_model(
|
|
82
|
+
"planning",
|
|
83
|
+
# Tool selection
|
|
84
|
+
selected_tools=(
|
|
85
|
+
List[Literal[tuple(selected_tools)]],
|
|
86
|
+
Field(
|
|
87
|
+
default=list(selected_tools.keys()),
|
|
88
|
+
json_schema_extra={'args_schemas': selected_tools}
|
|
89
|
+
)
|
|
90
|
+
),
|
|
91
|
+
__config__=ConfigDict(
|
|
92
|
+
json_schema_extra={
|
|
93
|
+
'metadata': {
|
|
94
|
+
"label": "Planning",
|
|
95
|
+
"description": "Tools for managing multi-step execution plans with progress tracking. Uses PostgreSQL when configured, filesystem otherwise.",
|
|
96
|
+
"icon_url": None,
|
|
97
|
+
"max_length": PlanningToolkit._toolkit_max_length,
|
|
98
|
+
"categories": ["planning", "internal_tool"],
|
|
99
|
+
"extra_categories": ["task management", "todo", "progress tracking"]
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
@classmethod
|
|
106
|
+
def get_toolkit(
|
|
107
|
+
cls,
|
|
108
|
+
toolkit_name: Optional[str] = None,
|
|
109
|
+
selected_tools: Optional[List[str]] = None,
|
|
110
|
+
pgvector_configuration: Optional[dict] = None,
|
|
111
|
+
storage_dir: Optional[str] = None,
|
|
112
|
+
plan_callback: Optional[Any] = None,
|
|
113
|
+
conversation_id: Optional[str] = None,
|
|
114
|
+
**kwargs
|
|
115
|
+
):
|
|
116
|
+
"""
|
|
117
|
+
Create a PlanningToolkit instance with configured tools.
|
|
118
|
+
|
|
119
|
+
Args:
|
|
120
|
+
toolkit_name: Optional name prefix for tools
|
|
121
|
+
selected_tools: List of tool names to include (default: all)
|
|
122
|
+
pgvector_configuration: PostgreSQL configuration dict with connection_string.
|
|
123
|
+
If not provided, uses filesystem storage.
|
|
124
|
+
storage_dir: Directory for filesystem storage (when no pgvector_configuration)
|
|
125
|
+
plan_callback: Optional callback function called when plan changes (for CLI UI)
|
|
126
|
+
conversation_id: Conversation ID for scoping plans.
|
|
127
|
+
For server: from elitea_core payload. For CLI: session_id.
|
|
128
|
+
**kwargs: Additional configuration options
|
|
129
|
+
|
|
130
|
+
Returns:
|
|
131
|
+
PlanningToolkit instance with configured tools
|
|
132
|
+
"""
|
|
133
|
+
if selected_tools is None:
|
|
134
|
+
selected_tools = ['update_plan', 'complete_step', 'get_plan_status', 'delete_plan']
|
|
135
|
+
|
|
136
|
+
tools = []
|
|
137
|
+
|
|
138
|
+
# Extract connection string from pgvector configuration (if provided)
|
|
139
|
+
connection_string = None
|
|
140
|
+
if pgvector_configuration:
|
|
141
|
+
connection_string = pgvector_configuration.get('connection_string', '')
|
|
142
|
+
if hasattr(connection_string, 'get_secret_value'):
|
|
143
|
+
connection_string = connection_string.get_secret_value()
|
|
144
|
+
|
|
145
|
+
# Create wrapper - it will auto-select storage backend
|
|
146
|
+
wrapper = PlanningWrapper(
|
|
147
|
+
connection_string=connection_string if connection_string else None,
|
|
148
|
+
conversation_id=conversation_id,
|
|
149
|
+
storage_dir=storage_dir,
|
|
150
|
+
plan_callback=plan_callback,
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
# Use clean toolkit name for context (max 1000 chars in description)
|
|
154
|
+
toolkit_context = f" [Toolkit: {clean_string(toolkit_name, 0)}]" if toolkit_name else ''
|
|
155
|
+
|
|
156
|
+
# Create tools from wrapper
|
|
157
|
+
available_tools = wrapper.get_available_tools()
|
|
158
|
+
for tool in available_tools:
|
|
159
|
+
if tool["name"] not in selected_tools:
|
|
160
|
+
continue
|
|
161
|
+
|
|
162
|
+
# Add toolkit context to description with character limit
|
|
163
|
+
description = tool["description"]
|
|
164
|
+
if toolkit_context and len(description + toolkit_context) <= 1000:
|
|
165
|
+
description = description + toolkit_context
|
|
166
|
+
|
|
167
|
+
tools.append(BaseAction(
|
|
168
|
+
api_wrapper=wrapper,
|
|
169
|
+
name=tool["name"],
|
|
170
|
+
description=description,
|
|
171
|
+
args_schema=tool["args_schema"]
|
|
172
|
+
))
|
|
173
|
+
|
|
174
|
+
return cls(tools=tools)
|
|
175
|
+
|
|
176
|
+
def get_tools(self) -> List[BaseTool]:
|
|
177
|
+
"""Return the list of configured tools."""
|
|
178
|
+
return self.tools
|
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
"""
|
|
2
|
+
SkillRouter Toolkit for configuring and accessing specialized skills.
|
|
3
|
+
|
|
4
|
+
This toolkit provides a configurable way to set up the skill router with
|
|
5
|
+
specific skills from filesystem or platform-hosted agents/pipelines.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import List, Optional, TYPE_CHECKING
|
|
9
|
+
from pydantic import create_model, BaseModel, Field, ConfigDict
|
|
10
|
+
from langchain_community.agent_toolkits.base import BaseToolkit
|
|
11
|
+
from langchain_core.tools import BaseTool
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from alita_sdk.clients import AlitaClient
|
|
15
|
+
|
|
16
|
+
from alita_sdk.tools.base.tool import BaseAction
|
|
17
|
+
from alita_sdk.tools.utils import clean_string
|
|
18
|
+
from ..skills import SkillsRegistry, SkillMetadata, SkillType, SkillSource
|
|
19
|
+
from ..tools.skill_router import SkillRouterWrapper
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class SkillConfig(BaseModel):
|
|
23
|
+
"""Configuration for a single skill."""
|
|
24
|
+
|
|
25
|
+
# Platform skill fields (type is implicit from parent field: agents or pipelines)
|
|
26
|
+
id: int = Field(description="Platform ID (for agent/pipeline skills)")
|
|
27
|
+
version_id: int = Field(description="Platform version ID (for agent/pipeline skills)")
|
|
28
|
+
name: Optional[str] = Field(default=None, description="Skill name (optional override)")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class SkillRouterToolkit(BaseToolkit):
|
|
32
|
+
"""Toolkit for configuring skill router with specific skills."""
|
|
33
|
+
|
|
34
|
+
tools: List[BaseTool] = []
|
|
35
|
+
|
|
36
|
+
@staticmethod
|
|
37
|
+
def toolkit_config_schema() -> BaseModel:
|
|
38
|
+
"""Define the configuration schema for the skill router toolkit."""
|
|
39
|
+
# Get available tools for selected_tools field
|
|
40
|
+
selected_tools_options = {x['name']: x['args_schema'].schema() for x in SkillRouterWrapper.model_construct().get_available_tools()}
|
|
41
|
+
|
|
42
|
+
return create_model(
|
|
43
|
+
"skill_router",
|
|
44
|
+
# Separate fields for agents and pipelines - optional but default to empty lists
|
|
45
|
+
agents=(Optional[List[SkillConfig]], Field(
|
|
46
|
+
description="List of agents to make available as skills",
|
|
47
|
+
default=[],
|
|
48
|
+
json_schema_extra={
|
|
49
|
+
"agent_tags": ["skill"]
|
|
50
|
+
}
|
|
51
|
+
)),
|
|
52
|
+
pipelines=(Optional[List[SkillConfig]], Field(
|
|
53
|
+
description="List of pipelines to make available as skills",
|
|
54
|
+
default=[],
|
|
55
|
+
json_schema_extra={
|
|
56
|
+
"pipeline_tags": ["skill"]
|
|
57
|
+
}
|
|
58
|
+
)),
|
|
59
|
+
prompt=(Optional[str], Field(
|
|
60
|
+
description="Custom system prompt for skill routing",
|
|
61
|
+
default="",
|
|
62
|
+
json_schema_extra={"lines": 4}
|
|
63
|
+
)),
|
|
64
|
+
timeout=(Optional[int], Field(description="Default timeout in seconds for skill execution", default=300)),
|
|
65
|
+
execution_mode=(Optional[str], Field(
|
|
66
|
+
description="Default execution mode for skills",
|
|
67
|
+
default=None,
|
|
68
|
+
json_schema_extra={"enum": ["subprocess", "remote"]}
|
|
69
|
+
)),
|
|
70
|
+
selected_tools=(List[str], Field(
|
|
71
|
+
description="List of tools to enable",
|
|
72
|
+
default=list(selected_tools_options.keys()),
|
|
73
|
+
json_schema_extra={'args_schemas': selected_tools_options}
|
|
74
|
+
)),
|
|
75
|
+
__config__=ConfigDict(json_schema_extra={'metadata': {"label": "Skill Router", "icon_url": None, "hidden": True}})
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
@classmethod
|
|
79
|
+
def get_toolkit(
|
|
80
|
+
cls,
|
|
81
|
+
client: 'AlitaClient',
|
|
82
|
+
llm = None,
|
|
83
|
+
toolkit_name: Optional[str] = None,
|
|
84
|
+
selected_tools: List[str] = None,
|
|
85
|
+
agents: List[SkillConfig] = None,
|
|
86
|
+
pipelines: List[SkillConfig] = None,
|
|
87
|
+
prompt: Optional[str] = None,
|
|
88
|
+
timeout: Optional[int] = None,
|
|
89
|
+
execution_mode: Optional[str] = None
|
|
90
|
+
):
|
|
91
|
+
"""Create a skill router toolkit with configured skills."""
|
|
92
|
+
|
|
93
|
+
if selected_tools is None:
|
|
94
|
+
selected_tools = []
|
|
95
|
+
|
|
96
|
+
# Create a custom registry for this toolkit
|
|
97
|
+
registry = SkillsRegistry(search_paths=[])
|
|
98
|
+
|
|
99
|
+
# Helper function to process skill configs
|
|
100
|
+
def add_skills_to_registry(skill_configs, skill_type):
|
|
101
|
+
if skill_configs:
|
|
102
|
+
for skill_config_dict in skill_configs:
|
|
103
|
+
# Convert dict to SkillConfig object
|
|
104
|
+
skill_config = SkillConfig(**skill_config_dict)
|
|
105
|
+
skill_metadata = cls._create_skill_from_config(skill_config, client, skill_type)
|
|
106
|
+
if skill_metadata:
|
|
107
|
+
# Add skill to registry manually
|
|
108
|
+
registry.discovery.cache[skill_metadata.name] = skill_metadata
|
|
109
|
+
|
|
110
|
+
# Add configured agents (if provided)
|
|
111
|
+
add_skills_to_registry(agents or [], "agent")
|
|
112
|
+
|
|
113
|
+
# Add configured pipelines (if provided)
|
|
114
|
+
add_skills_to_registry(pipelines or [], "pipeline")
|
|
115
|
+
|
|
116
|
+
# Create skill router wrapper with custom configuration
|
|
117
|
+
wrapper = SkillRouterWrapper(
|
|
118
|
+
registry=registry,
|
|
119
|
+
alita_client=client,
|
|
120
|
+
llm=llm,
|
|
121
|
+
enable_callbacks=True,
|
|
122
|
+
default_timeout=timeout,
|
|
123
|
+
default_execution_mode=execution_mode,
|
|
124
|
+
custom_prompt=prompt
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# Get available tools from wrapper
|
|
128
|
+
available_tools = wrapper.get_available_tools()
|
|
129
|
+
|
|
130
|
+
# Filter by selected_tools if provided
|
|
131
|
+
tools = []
|
|
132
|
+
toolkit_context = f" [Toolkit: {clean_string(toolkit_name, 0)}]" if toolkit_name else ''
|
|
133
|
+
|
|
134
|
+
for tool in available_tools:
|
|
135
|
+
if selected_tools:
|
|
136
|
+
if tool["name"] not in selected_tools:
|
|
137
|
+
continue
|
|
138
|
+
|
|
139
|
+
# Add toolkit context to description with character limit
|
|
140
|
+
description = tool["description"]
|
|
141
|
+
if toolkit_context and len(description + toolkit_context) <= 1000:
|
|
142
|
+
description = description + toolkit_context
|
|
143
|
+
|
|
144
|
+
# Wrap in BaseAction
|
|
145
|
+
tools.append(BaseAction(
|
|
146
|
+
api_wrapper=wrapper,
|
|
147
|
+
name=tool["name"],
|
|
148
|
+
description=description,
|
|
149
|
+
args_schema=tool["args_schema"],
|
|
150
|
+
metadata={"toolkit_name": toolkit_name, "toolkit_type": "skill_router"} if toolkit_name else {}
|
|
151
|
+
))
|
|
152
|
+
|
|
153
|
+
return cls(tools=tools)
|
|
154
|
+
|
|
155
|
+
@classmethod
|
|
156
|
+
def _create_skill_from_config(cls, config: SkillConfig, client: 'AlitaClient', skill_type: str) -> Optional[SkillMetadata]:
|
|
157
|
+
"""Create SkillMetadata from SkillConfig.
|
|
158
|
+
|
|
159
|
+
Args:
|
|
160
|
+
config: SkillConfig with id, version_id, and optional name
|
|
161
|
+
client: AlitaClient for fetching skill details
|
|
162
|
+
skill_type: Either "agent" or "pipeline" (from parent field)
|
|
163
|
+
"""
|
|
164
|
+
try:
|
|
165
|
+
# Get skill details from platform
|
|
166
|
+
if skill_type == "agent":
|
|
167
|
+
skill_details = cls._get_agent_details(client, config.id, config.version_id)
|
|
168
|
+
metadata_type = SkillType.AGENT
|
|
169
|
+
else: # pipeline
|
|
170
|
+
skill_details = cls._get_pipeline_details(client, config.id, config.version_id)
|
|
171
|
+
metadata_type = SkillType.PIPELINE
|
|
172
|
+
|
|
173
|
+
# Create SkillMetadata for platform skill
|
|
174
|
+
return SkillMetadata(
|
|
175
|
+
name=config.name or skill_details.get('name', f"{skill_type}_{config.id}"),
|
|
176
|
+
skill_type=metadata_type,
|
|
177
|
+
source=SkillSource.PLATFORM,
|
|
178
|
+
id=config.id,
|
|
179
|
+
version_id=config.version_id,
|
|
180
|
+
description=skill_details.get('description', ''),
|
|
181
|
+
capabilities=skill_details.get('capabilities', []),
|
|
182
|
+
tags=skill_details.get('tags', []),
|
|
183
|
+
version=skill_details.get('version', '1.0.0'),
|
|
184
|
+
# Set default execution config - platform skills run remotely
|
|
185
|
+
execution={"mode": "remote", "timeout": 300},
|
|
186
|
+
results={"format": "text_with_links"},
|
|
187
|
+
inputs={},
|
|
188
|
+
outputs={}
|
|
189
|
+
)
|
|
190
|
+
|
|
191
|
+
except Exception as e:
|
|
192
|
+
import logging
|
|
193
|
+
logging.getLogger(__name__).error(f"Failed to create skill from config {config}: {e}")
|
|
194
|
+
return None
|
|
195
|
+
|
|
196
|
+
@classmethod
|
|
197
|
+
def _get_agent_details(cls, client: 'AlitaClient', agent_id: int, version_id: int) -> dict:
|
|
198
|
+
"""Get agent details from platform."""
|
|
199
|
+
try:
|
|
200
|
+
app_details = client.get_app_details(agent_id)
|
|
201
|
+
version_details = client.get_app_version_details(agent_id, version_id)
|
|
202
|
+
|
|
203
|
+
return {
|
|
204
|
+
'name': app_details.get('name', f'agent_{agent_id}'),
|
|
205
|
+
'description': app_details.get('description', ''),
|
|
206
|
+
'capabilities': [], # Could be extracted from app metadata
|
|
207
|
+
'tags': [], # Could be extracted from app metadata
|
|
208
|
+
'version': version_details.get('version', '1.0.0')
|
|
209
|
+
}
|
|
210
|
+
except Exception as e:
|
|
211
|
+
import logging
|
|
212
|
+
logging.getLogger(__name__).error(f"Failed to get agent details for {agent_id}/{version_id}: {e}")
|
|
213
|
+
return {'name': f'agent_{agent_id}', 'description': 'Platform-hosted agent'}
|
|
214
|
+
|
|
215
|
+
@classmethod
|
|
216
|
+
def _get_pipeline_details(cls, client: 'AlitaClient', pipeline_id: int, version_id: int) -> dict:
|
|
217
|
+
"""Get pipeline details from platform."""
|
|
218
|
+
try:
|
|
219
|
+
# For now, use the same method as agents since they use the same API
|
|
220
|
+
# In the future, this might use a different endpoint for pipelines
|
|
221
|
+
app_details = client.get_app_details(pipeline_id)
|
|
222
|
+
version_details = client.get_app_version_details(pipeline_id, version_id)
|
|
223
|
+
|
|
224
|
+
return {
|
|
225
|
+
'name': app_details.get('name', f'pipeline_{pipeline_id}'),
|
|
226
|
+
'description': app_details.get('description', ''),
|
|
227
|
+
'capabilities': [], # Could be extracted from pipeline metadata
|
|
228
|
+
'tags': [], # Could be extracted from pipeline metadata
|
|
229
|
+
'version': version_details.get('version', '1.0.0')
|
|
230
|
+
}
|
|
231
|
+
except Exception as e:
|
|
232
|
+
import logging
|
|
233
|
+
logging.getLogger(__name__).error(f"Failed to get pipeline details for {pipeline_id}/{version_id}: {e}")
|
|
234
|
+
return {'name': f'pipeline_{pipeline_id}', 'description': 'Platform-hosted pipeline'}
|
|
235
|
+
|
|
236
|
+
def get_tools(self):
|
|
237
|
+
"""Get the configured tools."""
|
|
238
|
+
return self.tools
|