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.
Files changed (278) hide show
  1. alita_sdk/cli/__init__.py +10 -0
  2. alita_sdk/cli/__main__.py +17 -0
  3. alita_sdk/cli/agent/__init__.py +5 -0
  4. alita_sdk/cli/agent/default.py +258 -0
  5. alita_sdk/cli/agent_executor.py +156 -0
  6. alita_sdk/cli/agent_loader.py +245 -0
  7. alita_sdk/cli/agent_ui.py +228 -0
  8. alita_sdk/cli/agents.py +3113 -0
  9. alita_sdk/cli/callbacks.py +647 -0
  10. alita_sdk/cli/cli.py +168 -0
  11. alita_sdk/cli/config.py +306 -0
  12. alita_sdk/cli/context/__init__.py +30 -0
  13. alita_sdk/cli/context/cleanup.py +198 -0
  14. alita_sdk/cli/context/manager.py +731 -0
  15. alita_sdk/cli/context/message.py +285 -0
  16. alita_sdk/cli/context/strategies.py +289 -0
  17. alita_sdk/cli/context/token_estimation.py +127 -0
  18. alita_sdk/cli/formatting.py +182 -0
  19. alita_sdk/cli/input_handler.py +419 -0
  20. alita_sdk/cli/inventory.py +1073 -0
  21. alita_sdk/cli/mcp_loader.py +315 -0
  22. alita_sdk/cli/testcases/__init__.py +94 -0
  23. alita_sdk/cli/testcases/data_generation.py +119 -0
  24. alita_sdk/cli/testcases/discovery.py +96 -0
  25. alita_sdk/cli/testcases/executor.py +84 -0
  26. alita_sdk/cli/testcases/logger.py +85 -0
  27. alita_sdk/cli/testcases/parser.py +172 -0
  28. alita_sdk/cli/testcases/prompts.py +91 -0
  29. alita_sdk/cli/testcases/reporting.py +125 -0
  30. alita_sdk/cli/testcases/setup.py +108 -0
  31. alita_sdk/cli/testcases/test_runner.py +282 -0
  32. alita_sdk/cli/testcases/utils.py +39 -0
  33. alita_sdk/cli/testcases/validation.py +90 -0
  34. alita_sdk/cli/testcases/workflow.py +196 -0
  35. alita_sdk/cli/toolkit.py +327 -0
  36. alita_sdk/cli/toolkit_loader.py +85 -0
  37. alita_sdk/cli/tools/__init__.py +43 -0
  38. alita_sdk/cli/tools/approval.py +224 -0
  39. alita_sdk/cli/tools/filesystem.py +1751 -0
  40. alita_sdk/cli/tools/planning.py +389 -0
  41. alita_sdk/cli/tools/terminal.py +414 -0
  42. alita_sdk/community/__init__.py +72 -12
  43. alita_sdk/community/inventory/__init__.py +236 -0
  44. alita_sdk/community/inventory/config.py +257 -0
  45. alita_sdk/community/inventory/enrichment.py +2137 -0
  46. alita_sdk/community/inventory/extractors.py +1469 -0
  47. alita_sdk/community/inventory/ingestion.py +3172 -0
  48. alita_sdk/community/inventory/knowledge_graph.py +1457 -0
  49. alita_sdk/community/inventory/parsers/__init__.py +218 -0
  50. alita_sdk/community/inventory/parsers/base.py +295 -0
  51. alita_sdk/community/inventory/parsers/csharp_parser.py +907 -0
  52. alita_sdk/community/inventory/parsers/go_parser.py +851 -0
  53. alita_sdk/community/inventory/parsers/html_parser.py +389 -0
  54. alita_sdk/community/inventory/parsers/java_parser.py +593 -0
  55. alita_sdk/community/inventory/parsers/javascript_parser.py +629 -0
  56. alita_sdk/community/inventory/parsers/kotlin_parser.py +768 -0
  57. alita_sdk/community/inventory/parsers/markdown_parser.py +362 -0
  58. alita_sdk/community/inventory/parsers/python_parser.py +604 -0
  59. alita_sdk/community/inventory/parsers/rust_parser.py +858 -0
  60. alita_sdk/community/inventory/parsers/swift_parser.py +832 -0
  61. alita_sdk/community/inventory/parsers/text_parser.py +322 -0
  62. alita_sdk/community/inventory/parsers/yaml_parser.py +370 -0
  63. alita_sdk/community/inventory/patterns/__init__.py +61 -0
  64. alita_sdk/community/inventory/patterns/ast_adapter.py +380 -0
  65. alita_sdk/community/inventory/patterns/loader.py +348 -0
  66. alita_sdk/community/inventory/patterns/registry.py +198 -0
  67. alita_sdk/community/inventory/presets.py +535 -0
  68. alita_sdk/community/inventory/retrieval.py +1403 -0
  69. alita_sdk/community/inventory/toolkit.py +173 -0
  70. alita_sdk/community/inventory/toolkit_utils.py +176 -0
  71. alita_sdk/community/inventory/visualize.py +1370 -0
  72. alita_sdk/configurations/__init__.py +1 -1
  73. alita_sdk/configurations/ado.py +141 -20
  74. alita_sdk/configurations/bitbucket.py +94 -2
  75. alita_sdk/configurations/confluence.py +130 -1
  76. alita_sdk/configurations/figma.py +76 -0
  77. alita_sdk/configurations/gitlab.py +91 -0
  78. alita_sdk/configurations/jira.py +103 -0
  79. alita_sdk/configurations/openapi.py +329 -0
  80. alita_sdk/configurations/qtest.py +72 -1
  81. alita_sdk/configurations/report_portal.py +96 -0
  82. alita_sdk/configurations/sharepoint.py +148 -0
  83. alita_sdk/configurations/testio.py +83 -0
  84. alita_sdk/configurations/testrail.py +88 -0
  85. alita_sdk/configurations/xray.py +93 -0
  86. alita_sdk/configurations/zephyr_enterprise.py +93 -0
  87. alita_sdk/configurations/zephyr_essential.py +75 -0
  88. alita_sdk/runtime/clients/artifact.py +3 -3
  89. alita_sdk/runtime/clients/client.py +388 -46
  90. alita_sdk/runtime/clients/mcp_discovery.py +342 -0
  91. alita_sdk/runtime/clients/mcp_manager.py +262 -0
  92. alita_sdk/runtime/clients/sandbox_client.py +8 -21
  93. alita_sdk/runtime/langchain/_constants_bkup.py +1318 -0
  94. alita_sdk/runtime/langchain/assistant.py +157 -39
  95. alita_sdk/runtime/langchain/constants.py +647 -1
  96. alita_sdk/runtime/langchain/document_loaders/AlitaDocxMammothLoader.py +315 -3
  97. alita_sdk/runtime/langchain/document_loaders/AlitaExcelLoader.py +103 -60
  98. alita_sdk/runtime/langchain/document_loaders/AlitaJSONLinesLoader.py +77 -0
  99. alita_sdk/runtime/langchain/document_loaders/AlitaJSONLoader.py +10 -4
  100. alita_sdk/runtime/langchain/document_loaders/AlitaPowerPointLoader.py +226 -7
  101. alita_sdk/runtime/langchain/document_loaders/AlitaTextLoader.py +5 -2
  102. alita_sdk/runtime/langchain/document_loaders/constants.py +40 -19
  103. alita_sdk/runtime/langchain/langraph_agent.py +405 -84
  104. alita_sdk/runtime/langchain/utils.py +106 -7
  105. alita_sdk/runtime/llms/preloaded.py +2 -6
  106. alita_sdk/runtime/models/mcp_models.py +61 -0
  107. alita_sdk/runtime/skills/__init__.py +91 -0
  108. alita_sdk/runtime/skills/callbacks.py +498 -0
  109. alita_sdk/runtime/skills/discovery.py +540 -0
  110. alita_sdk/runtime/skills/executor.py +610 -0
  111. alita_sdk/runtime/skills/input_builder.py +371 -0
  112. alita_sdk/runtime/skills/models.py +330 -0
  113. alita_sdk/runtime/skills/registry.py +355 -0
  114. alita_sdk/runtime/skills/skill_runner.py +330 -0
  115. alita_sdk/runtime/toolkits/__init__.py +31 -0
  116. alita_sdk/runtime/toolkits/application.py +29 -10
  117. alita_sdk/runtime/toolkits/artifact.py +20 -11
  118. alita_sdk/runtime/toolkits/datasource.py +13 -6
  119. alita_sdk/runtime/toolkits/mcp.py +783 -0
  120. alita_sdk/runtime/toolkits/mcp_config.py +1048 -0
  121. alita_sdk/runtime/toolkits/planning.py +178 -0
  122. alita_sdk/runtime/toolkits/skill_router.py +238 -0
  123. alita_sdk/runtime/toolkits/subgraph.py +251 -6
  124. alita_sdk/runtime/toolkits/tools.py +356 -69
  125. alita_sdk/runtime/toolkits/vectorstore.py +11 -5
  126. alita_sdk/runtime/tools/__init__.py +10 -3
  127. alita_sdk/runtime/tools/application.py +27 -6
  128. alita_sdk/runtime/tools/artifact.py +511 -28
  129. alita_sdk/runtime/tools/data_analysis.py +183 -0
  130. alita_sdk/runtime/tools/function.py +67 -35
  131. alita_sdk/runtime/tools/graph.py +10 -4
  132. alita_sdk/runtime/tools/image_generation.py +148 -46
  133. alita_sdk/runtime/tools/llm.py +1003 -128
  134. alita_sdk/runtime/tools/loop.py +3 -1
  135. alita_sdk/runtime/tools/loop_output.py +3 -1
  136. alita_sdk/runtime/tools/mcp_inspect_tool.py +284 -0
  137. alita_sdk/runtime/tools/mcp_remote_tool.py +181 -0
  138. alita_sdk/runtime/tools/mcp_server_tool.py +8 -5
  139. alita_sdk/runtime/tools/planning/__init__.py +36 -0
  140. alita_sdk/runtime/tools/planning/models.py +246 -0
  141. alita_sdk/runtime/tools/planning/wrapper.py +607 -0
  142. alita_sdk/runtime/tools/router.py +2 -4
  143. alita_sdk/runtime/tools/sandbox.py +65 -48
  144. alita_sdk/runtime/tools/skill_router.py +776 -0
  145. alita_sdk/runtime/tools/tool.py +3 -1
  146. alita_sdk/runtime/tools/vectorstore.py +9 -3
  147. alita_sdk/runtime/tools/vectorstore_base.py +70 -14
  148. alita_sdk/runtime/utils/AlitaCallback.py +137 -21
  149. alita_sdk/runtime/utils/constants.py +5 -1
  150. alita_sdk/runtime/utils/mcp_client.py +492 -0
  151. alita_sdk/runtime/utils/mcp_oauth.py +361 -0
  152. alita_sdk/runtime/utils/mcp_sse_client.py +434 -0
  153. alita_sdk/runtime/utils/mcp_tools_discovery.py +124 -0
  154. alita_sdk/runtime/utils/serialization.py +155 -0
  155. alita_sdk/runtime/utils/streamlit.py +40 -13
  156. alita_sdk/runtime/utils/toolkit_utils.py +30 -9
  157. alita_sdk/runtime/utils/utils.py +36 -0
  158. alita_sdk/tools/__init__.py +134 -35
  159. alita_sdk/tools/ado/repos/__init__.py +51 -32
  160. alita_sdk/tools/ado/repos/repos_wrapper.py +148 -89
  161. alita_sdk/tools/ado/test_plan/__init__.py +25 -9
  162. alita_sdk/tools/ado/test_plan/test_plan_wrapper.py +23 -1
  163. alita_sdk/tools/ado/utils.py +1 -18
  164. alita_sdk/tools/ado/wiki/__init__.py +25 -12
  165. alita_sdk/tools/ado/wiki/ado_wrapper.py +291 -22
  166. alita_sdk/tools/ado/work_item/__init__.py +26 -13
  167. alita_sdk/tools/ado/work_item/ado_wrapper.py +73 -11
  168. alita_sdk/tools/advanced_jira_mining/__init__.py +11 -8
  169. alita_sdk/tools/aws/delta_lake/__init__.py +13 -9
  170. alita_sdk/tools/aws/delta_lake/tool.py +5 -1
  171. alita_sdk/tools/azure_ai/search/__init__.py +11 -8
  172. alita_sdk/tools/azure_ai/search/api_wrapper.py +1 -1
  173. alita_sdk/tools/base/tool.py +5 -1
  174. alita_sdk/tools/base_indexer_toolkit.py +271 -84
  175. alita_sdk/tools/bitbucket/__init__.py +17 -11
  176. alita_sdk/tools/bitbucket/api_wrapper.py +59 -11
  177. alita_sdk/tools/bitbucket/cloud_api_wrapper.py +49 -35
  178. alita_sdk/tools/browser/__init__.py +5 -4
  179. alita_sdk/tools/carrier/__init__.py +5 -6
  180. alita_sdk/tools/carrier/backend_reports_tool.py +6 -6
  181. alita_sdk/tools/carrier/run_ui_test_tool.py +6 -6
  182. alita_sdk/tools/carrier/ui_reports_tool.py +5 -5
  183. alita_sdk/tools/chunkers/__init__.py +3 -1
  184. alita_sdk/tools/chunkers/code/treesitter/treesitter.py +37 -13
  185. alita_sdk/tools/chunkers/sematic/json_chunker.py +1 -0
  186. alita_sdk/tools/chunkers/sematic/markdown_chunker.py +97 -6
  187. alita_sdk/tools/chunkers/sematic/proposal_chunker.py +1 -1
  188. alita_sdk/tools/chunkers/universal_chunker.py +270 -0
  189. alita_sdk/tools/cloud/aws/__init__.py +10 -7
  190. alita_sdk/tools/cloud/azure/__init__.py +10 -7
  191. alita_sdk/tools/cloud/gcp/__init__.py +10 -7
  192. alita_sdk/tools/cloud/k8s/__init__.py +10 -7
  193. alita_sdk/tools/code/linter/__init__.py +10 -8
  194. alita_sdk/tools/code/loaders/codesearcher.py +3 -2
  195. alita_sdk/tools/code/sonar/__init__.py +11 -8
  196. alita_sdk/tools/code_indexer_toolkit.py +82 -22
  197. alita_sdk/tools/confluence/__init__.py +22 -16
  198. alita_sdk/tools/confluence/api_wrapper.py +107 -30
  199. alita_sdk/tools/confluence/loader.py +14 -2
  200. alita_sdk/tools/custom_open_api/__init__.py +12 -5
  201. alita_sdk/tools/elastic/__init__.py +11 -8
  202. alita_sdk/tools/elitea_base.py +493 -30
  203. alita_sdk/tools/figma/__init__.py +58 -11
  204. alita_sdk/tools/figma/api_wrapper.py +1235 -143
  205. alita_sdk/tools/figma/figma_client.py +73 -0
  206. alita_sdk/tools/figma/toon_tools.py +2748 -0
  207. alita_sdk/tools/github/__init__.py +14 -15
  208. alita_sdk/tools/github/github_client.py +224 -100
  209. alita_sdk/tools/github/graphql_client_wrapper.py +119 -33
  210. alita_sdk/tools/github/schemas.py +14 -5
  211. alita_sdk/tools/github/tool.py +5 -1
  212. alita_sdk/tools/github/tool_prompts.py +9 -22
  213. alita_sdk/tools/gitlab/__init__.py +16 -11
  214. alita_sdk/tools/gitlab/api_wrapper.py +218 -48
  215. alita_sdk/tools/gitlab_org/__init__.py +10 -9
  216. alita_sdk/tools/gitlab_org/api_wrapper.py +63 -64
  217. alita_sdk/tools/google/bigquery/__init__.py +13 -12
  218. alita_sdk/tools/google/bigquery/tool.py +5 -1
  219. alita_sdk/tools/google_places/__init__.py +11 -8
  220. alita_sdk/tools/google_places/api_wrapper.py +1 -1
  221. alita_sdk/tools/jira/__init__.py +17 -10
  222. alita_sdk/tools/jira/api_wrapper.py +92 -41
  223. alita_sdk/tools/keycloak/__init__.py +11 -8
  224. alita_sdk/tools/localgit/__init__.py +9 -3
  225. alita_sdk/tools/localgit/local_git.py +62 -54
  226. alita_sdk/tools/localgit/tool.py +5 -1
  227. alita_sdk/tools/memory/__init__.py +12 -4
  228. alita_sdk/tools/non_code_indexer_toolkit.py +1 -0
  229. alita_sdk/tools/ocr/__init__.py +11 -8
  230. alita_sdk/tools/openapi/__init__.py +491 -106
  231. alita_sdk/tools/openapi/api_wrapper.py +1368 -0
  232. alita_sdk/tools/openapi/tool.py +20 -0
  233. alita_sdk/tools/pandas/__init__.py +20 -12
  234. alita_sdk/tools/pandas/api_wrapper.py +38 -25
  235. alita_sdk/tools/pandas/dataframe/generator/base.py +3 -1
  236. alita_sdk/tools/postman/__init__.py +10 -9
  237. alita_sdk/tools/pptx/__init__.py +11 -10
  238. alita_sdk/tools/pptx/pptx_wrapper.py +1 -1
  239. alita_sdk/tools/qtest/__init__.py +31 -11
  240. alita_sdk/tools/qtest/api_wrapper.py +2135 -86
  241. alita_sdk/tools/rally/__init__.py +10 -9
  242. alita_sdk/tools/rally/api_wrapper.py +1 -1
  243. alita_sdk/tools/report_portal/__init__.py +12 -8
  244. alita_sdk/tools/salesforce/__init__.py +10 -8
  245. alita_sdk/tools/servicenow/__init__.py +17 -15
  246. alita_sdk/tools/servicenow/api_wrapper.py +1 -1
  247. alita_sdk/tools/sharepoint/__init__.py +10 -7
  248. alita_sdk/tools/sharepoint/api_wrapper.py +129 -38
  249. alita_sdk/tools/sharepoint/authorization_helper.py +191 -1
  250. alita_sdk/tools/sharepoint/utils.py +8 -2
  251. alita_sdk/tools/slack/__init__.py +10 -7
  252. alita_sdk/tools/slack/api_wrapper.py +2 -2
  253. alita_sdk/tools/sql/__init__.py +12 -9
  254. alita_sdk/tools/testio/__init__.py +10 -7
  255. alita_sdk/tools/testrail/__init__.py +11 -10
  256. alita_sdk/tools/testrail/api_wrapper.py +1 -1
  257. alita_sdk/tools/utils/__init__.py +9 -4
  258. alita_sdk/tools/utils/content_parser.py +103 -18
  259. alita_sdk/tools/utils/text_operations.py +410 -0
  260. alita_sdk/tools/utils/tool_prompts.py +79 -0
  261. alita_sdk/tools/vector_adapters/VectorStoreAdapter.py +30 -13
  262. alita_sdk/tools/xray/__init__.py +13 -9
  263. alita_sdk/tools/yagmail/__init__.py +9 -3
  264. alita_sdk/tools/zephyr/__init__.py +10 -7
  265. alita_sdk/tools/zephyr_enterprise/__init__.py +11 -7
  266. alita_sdk/tools/zephyr_essential/__init__.py +10 -7
  267. alita_sdk/tools/zephyr_essential/api_wrapper.py +30 -13
  268. alita_sdk/tools/zephyr_essential/client.py +2 -2
  269. alita_sdk/tools/zephyr_scale/__init__.py +11 -8
  270. alita_sdk/tools/zephyr_scale/api_wrapper.py +2 -2
  271. alita_sdk/tools/zephyr_squad/__init__.py +10 -7
  272. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/METADATA +154 -8
  273. alita_sdk-0.3.627.dist-info/RECORD +468 -0
  274. alita_sdk-0.3.627.dist-info/entry_points.txt +2 -0
  275. alita_sdk-0.3.379.dist-info/RECORD +0 -360
  276. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/WHEEL +0 -0
  277. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/licenses/LICENSE +0 -0
  278. {alita_sdk-0.3.379.dist-info → alita_sdk-0.3.627.dist-info}/top_level.txt +0 -0
@@ -8,7 +8,8 @@ from pydantic import create_model, BaseModel, Field, SecretStr
8
8
  from ..base.tool import BaseAction
9
9
  from .api_wrapper import ZephyrV1ApiWrapper
10
10
  from ..elitea_base import filter_missconfigured_index_tools
11
- from ..utils import clean_string, TOOLKIT_SPLITTER, get_max_toolkit_length
11
+ from ..utils import clean_string, get_max_toolkit_length
12
+ from ...runtime.utils.constants import TOOLKIT_NAME_META, TOOL_NAME_META, TOOLKIT_TYPE_META
12
13
 
13
14
  name = "zephyr"
14
15
 
@@ -23,15 +24,13 @@ def get_tools(tool):
23
24
 
24
25
  class ZephyrToolkit(BaseToolkit):
25
26
  tools: List[BaseTool] = []
26
- toolkit_max_length: int = 0
27
27
 
28
28
  @staticmethod
29
29
  def toolkit_config_schema() -> BaseModel:
30
30
  selected_tools = {x['name']: x['args_schema'].schema() for x in ZephyrV1ApiWrapper.model_construct().get_available_tools()}
31
- ZephyrToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
32
31
  return create_model(
33
32
  name,
34
- base_url=(str, Field(description="Base URL", json_schema_extra={'toolkit_name': True, 'max_toolkit_length': ZephyrToolkit.toolkit_max_length})),
33
+ base_url=(str, Field(description="Base URL")),
35
34
  username=(str, Field(description="Username")),
36
35
  password=(SecretStr, Field(description="Password", json_schema_extra={'secret': True})),
37
36
  selected_tools=(List[Literal[tuple(selected_tools)]], Field(default=[], json_schema_extra={'args_schemas': selected_tools})),
@@ -49,18 +48,22 @@ class ZephyrToolkit(BaseToolkit):
49
48
  @filter_missconfigured_index_tools
50
49
  def get_toolkit(cls, selected_tools: list[str] | None = None, toolkit_name: Optional[str] = None, **kwargs):
51
50
  zephyr_api_wrapper = ZephyrV1ApiWrapper(**kwargs)
52
- prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
53
51
  available_tools = zephyr_api_wrapper.get_available_tools()
54
52
  tools = []
55
53
  for tool in available_tools:
56
54
  if selected_tools:
57
55
  if tool["name"] not in selected_tools:
58
56
  continue
57
+ description = tool["description"]
58
+ if toolkit_name:
59
+ description = f"Toolkit: {toolkit_name}\n{description}"
60
+ description = description[:1000]
59
61
  tools.append(BaseAction(
60
62
  api_wrapper=zephyr_api_wrapper,
61
63
  name=tool["name"],
62
- description=tool["description"],
63
- args_schema=tool["args_schema"]
64
+ description=description,
65
+ args_schema=tool["args_schema"],
66
+ metadata={TOOLKIT_NAME_META: toolkit_name, TOOLKIT_TYPE_META: name, TOOL_NAME_META: tool["name"]} if toolkit_name else {TOOL_NAME_META: tool["name"]}
64
67
  ))
65
68
  return cls(tools=tools)
66
69
 
@@ -5,9 +5,10 @@ from typing import List, Literal, Optional
5
5
  from .api_wrapper import ZephyrApiWrapper
6
6
  from ..base.tool import BaseAction
7
7
  from ..elitea_base import filter_missconfigured_index_tools
8
- from ..utils import clean_string, get_max_toolkit_length, TOOLKIT_SPLITTER
8
+ from ..utils import clean_string, get_max_toolkit_length
9
9
  from ...configurations.pgvector import PgVectorConfiguration
10
10
  from ...configurations.zephyr_enterprise import ZephyrEnterpriseConfiguration
11
+ from ...runtime.utils.constants import TOOLKIT_NAME_META, TOOL_NAME_META, TOOLKIT_TYPE_META
11
12
 
12
13
  name = "zephyr_enterprise"
13
14
 
@@ -28,13 +29,11 @@ def get_tools(tool):
28
29
 
29
30
  class ZephyrEnterpriseToolkit(BaseToolkit):
30
31
  tools: List[BaseTool] = []
31
- toolkit_max_length: int = 0
32
32
 
33
33
  @staticmethod
34
34
  def toolkit_config_schema() -> BaseModel:
35
35
  selected_tools = {x['name']: x['args_schema'].schema() for x in
36
36
  ZephyrApiWrapper.model_construct().get_available_tools()}
37
- ZephyrEnterpriseToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
38
37
  return create_model(
39
38
  name,
40
39
  zephyr_configuration=(ZephyrEnterpriseConfiguration, Field(description="Zephyr Configuration", json_schema_extra={'configuration_types': ['zephyr_enterprise']})),
@@ -67,17 +66,22 @@ class ZephyrEnterpriseToolkit(BaseToolkit):
67
66
  **(kwargs.get('embedding_configuration') or {}),
68
67
  }
69
68
  zephyr_api_wrapper = ZephyrApiWrapper(**wrapper_payload)
70
- prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
71
69
  available_tools = zephyr_api_wrapper.get_available_tools()
72
70
  tools = []
73
71
  for tool in available_tools:
74
72
  if selected_tools and tool["name"] not in selected_tools:
75
73
  continue
74
+ description = tool["description"]
75
+ if toolkit_name:
76
+ description = f"Toolkit: {toolkit_name}\n{description}"
77
+ description = description + "\nZephyr Enterprise instance: " + zephyr_api_wrapper.base_url
78
+ description = description[:1000]
76
79
  tools.append(BaseAction(
77
80
  api_wrapper=zephyr_api_wrapper,
78
- name=prefix + tool["name"],
79
- description=tool["description"] + "\nZephyr Enterprise instance: " + zephyr_api_wrapper.base_url,
80
- args_schema=tool["args_schema"]
81
+ name=tool["name"],
82
+ description=description,
83
+ args_schema=tool["args_schema"],
84
+ metadata={TOOLKIT_NAME_META: toolkit_name, TOOLKIT_TYPE_META: name, TOOL_NAME_META: tool["name"]} if toolkit_name else {TOOL_NAME_META: tool["name"]}
81
85
  ))
82
86
  return cls(tools=tools)
83
87
 
@@ -6,9 +6,10 @@ from pydantic import create_model, BaseModel, Field
6
6
  from .api_wrapper import ZephyrEssentialApiWrapper
7
7
  from ..base.tool import BaseAction
8
8
  from ..elitea_base import filter_missconfigured_index_tools
9
- from ..utils import clean_string, TOOLKIT_SPLITTER, get_max_toolkit_length
9
+ from ..utils import clean_string, get_max_toolkit_length
10
10
  from ...configurations.pgvector import PgVectorConfiguration
11
11
  from ...configurations.zephyr_essential import ZephyrEssentialConfiguration
12
+ from ...runtime.utils.constants import TOOLKIT_NAME_META, TOOL_NAME_META, TOOLKIT_TYPE_META
12
13
 
13
14
  name = "zephyr_essential"
14
15
 
@@ -29,12 +30,10 @@ def get_tools(tool):
29
30
 
30
31
  class ZephyrEssentialToolkit(BaseToolkit):
31
32
  tools: List[BaseTool] = []
32
- toolkit_max_length: int = 0
33
33
 
34
34
  @staticmethod
35
35
  def toolkit_config_schema() -> BaseModel:
36
36
  selected_tools = {x['name']: x['args_schema'].schema() for x in ZephyrEssentialApiWrapper.model_construct().get_available_tools()}
37
- ZephyrEssentialToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
38
37
  return create_model(
39
38
  name,
40
39
  zephyr_essential_configuration=(ZephyrEssentialConfiguration, Field(description="Zephyr Essential Configuration", json_schema_extra={'configuration_types': ['zephyr_essential']})),
@@ -62,18 +61,22 @@ class ZephyrEssentialToolkit(BaseToolkit):
62
61
  **(kwargs.get('pgvector_configuration') or {}),
63
62
  }
64
63
  zephyr_api_wrapper = ZephyrEssentialApiWrapper(**wrapper_payload)
65
- prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
66
64
  available_tools = zephyr_api_wrapper.get_available_tools()
67
65
  tools = []
68
66
  for tool in available_tools:
69
67
  if selected_tools:
70
68
  if tool["name"] not in selected_tools:
71
69
  continue
70
+ description = tool["description"]
71
+ if toolkit_name:
72
+ description = f"Toolkit: {toolkit_name}\n{description}"
73
+ description = description[:1000]
72
74
  tools.append(BaseAction(
73
75
  api_wrapper=zephyr_api_wrapper,
74
- name=prefix + tool["name"],
75
- description=tool["description"],
76
- args_schema=tool["args_schema"]
76
+ name=tool["name"],
77
+ description=description,
78
+ args_schema=tool["args_schema"],
79
+ metadata={TOOLKIT_NAME_META: toolkit_name, TOOLKIT_TYPE_META: name, TOOL_NAME_META: tool["name"]} if toolkit_name else {TOOL_NAME_META: tool["name"]}
77
80
  ))
78
81
  return cls(tools=tools)
79
82
 
@@ -1,3 +1,4 @@
1
+ import hashlib
1
2
  import json
2
3
  import logging
3
4
  from typing import Optional, Generator, Literal
@@ -55,6 +56,7 @@ class ZephyrEssentialApiWrapper(NonCodeIndexerToolkit):
55
56
  def create_test_case_issue_link(self, test_case_key: str, json: str):
56
57
  """Create an issue link for a test case."""
57
58
  issue_link_data = self._parse_json(json)
59
+ self._validate_issue_link_data(issue_link_data, "test case")
58
60
  return self._client.create_test_case_issue_link(test_case_key, issue_link_data)
59
61
 
60
62
  def create_test_case_web_link(self, test_case_key: str, json: str):
@@ -119,6 +121,7 @@ class ZephyrEssentialApiWrapper(NonCodeIndexerToolkit):
119
121
  def create_test_cycle_issue_link(self, test_cycle_id_or_key: str, json: str):
120
122
  """Create an issue link for a test cycle."""
121
123
  issue_link_data = self._parse_json(json)
124
+ self._validate_issue_link_data(issue_link_data, "test cycle")
122
125
  return self._client.create_test_cycle_issue_link(test_cycle_id_or_key, issue_link_data)
123
126
 
124
127
  def create_test_cycle_web_link(self, test_cycle_id_or_key: str, json: str):
@@ -164,6 +167,7 @@ class ZephyrEssentialApiWrapper(NonCodeIndexerToolkit):
164
167
  def create_test_execution_issue_link(self, test_execution_id_or_key: str, json: str):
165
168
  """Create an issue link for a test execution."""
166
169
  issue_link_data = self._parse_json(json)
170
+ self._validate_issue_link_data(issue_link_data, "test execution")
167
171
  return self._client.create_test_execution_issue_link(test_execution_id_or_key, issue_link_data)
168
172
 
169
173
  def list_projects(self, max_results: int = None, start_at: int = None):
@@ -266,6 +270,21 @@ class ZephyrEssentialApiWrapper(NonCodeIndexerToolkit):
266
270
  except json.JSONDecodeError as e:
267
271
  raise ValueError(f"Invalid JSON string: {str(e)}")
268
272
 
273
+ def _validate_issue_link_data(self, issue_link_data: dict, entity_type: str):
274
+ """Validate issue link payload has issueId, not issueKey."""
275
+ if 'issueId' not in issue_link_data:
276
+ if 'issueKey' in issue_link_data:
277
+ raise ToolException(
278
+ f"Zephyr Essential API requires 'issueId' (numeric Jira issue ID), "
279
+ f"not 'issueKey'. You provided issueKey='{issue_link_data['issueKey']}'. "
280
+ f"To find the issueId, Jira toolkit can be used or raw Jira API: GET /rest/api/2/issue/{issue_link_data['issueKey']} "
281
+ f"and look for the 'id' field in the response."
282
+ )
283
+ raise ToolException(
284
+ f"Missing required field 'issueId' in JSON payload for {entity_type} issue link. "
285
+ f"Example: {{\"issueId\": 10100}}"
286
+ )
287
+
269
288
  def _index_tool_params(self):
270
289
  return {
271
290
  'chunking_tool':(Literal['json', ''], Field(description="Name of chunking tool", default='json'))
@@ -284,22 +303,20 @@ class ZephyrEssentialApiWrapper(NonCodeIndexerToolkit):
284
303
  if isinstance(v, (str, int, float, bool, list, dict))
285
304
  }
286
305
  metadata['type'] = "TEST_CASE"
287
-
288
- yield Document(page_content="", metadata=metadata)
289
-
290
- def _extend_data(self, documents: Generator[Document, None, None]) -> Generator[Document, None, None]:
291
- for document in documents:
306
+ #
292
307
  try:
293
- if 'type' in document.metadata and document.metadata['type'] == "TEST_CASE":
294
- additional_content = self._process_test_case(document.metadata['key'])
295
- for steps_type, content in additional_content.items():
296
- if content:
297
- page_content = json.dumps(content)
298
- document.metadata[IndexerKeywords.CONTENT_IN_BYTES.value] = page_content.encode('utf-8')
299
- document.metadata["steps_type"] = steps_type
308
+ additional_content = self._process_test_case(metadata['key'])
309
+ for steps_type, content in additional_content.items():
310
+ if content:
311
+ page_content = json.dumps(content)
312
+ content_hash = hashlib.sha256(page_content.encode('utf-8')).hexdigest()
313
+ metadata[IndexerKeywords.UPDATED_ON.value] = content_hash
314
+ metadata[IndexerKeywords.CONTENT_IN_BYTES.value] = page_content.encode('utf-8')
315
+ metadata["steps_type"] = steps_type
300
316
  except Exception as e:
301
317
  logging.error(f"Failed to process document: {e}")
302
- yield document
318
+ #
319
+ yield Document(page_content="", metadata=metadata)
303
320
 
304
321
  def _process_test_case(self, key) -> dict:
305
322
  steps = self.get_test_case_test_steps(key)
@@ -19,9 +19,9 @@ class ZephyrEssentialAPI:
19
19
  if resp.headers.get("Content-Type", "").startswith("application/json"):
20
20
  return resp.json()
21
21
  return resp.text
22
- return ToolException(f"Error performing request {method} {api_path}: {resp.content}")
22
+ return ToolException(f"Unexpected status code {resp.status_code} for {method} {api_path}: {resp.content}")
23
23
  except requests.RequestException as e:
24
- raise Exception(f"Error performing request {method} {api_path}: {str(e)}")
24
+ raise Exception(f"Unexpected error while performing request {method} {api_path}: {str(e)}")
25
25
 
26
26
  # Test Cases
27
27
  def list_test_cases(self, project_key=None, folder_id=None, max_results=10, start_at=0):
@@ -7,9 +7,10 @@ from pydantic import create_model, BaseModel, Field
7
7
  from .api_wrapper import ZephyrScaleApiWrapper
8
8
  from ..base.tool import BaseAction
9
9
  from ..elitea_base import filter_missconfigured_index_tools
10
- from ..utils import clean_string, get_max_toolkit_length, TOOLKIT_SPLITTER
10
+ from ..utils import clean_string, get_max_toolkit_length
11
11
  from ...configurations.pgvector import PgVectorConfiguration
12
12
  from ...configurations.zephyr import ZephyrConfiguration
13
+ from ...runtime.utils.constants import TOOLKIT_NAME_META, TOOL_NAME_META, TOOLKIT_TYPE_META
13
14
 
14
15
  name = "zephyr_scale"
15
16
 
@@ -32,15 +33,13 @@ def get_tools(tool):
32
33
 
33
34
  class ZephyrScaleToolkit(BaseToolkit):
34
35
  tools: List[BaseTool] = []
35
- toolkit_max_length: int = 0
36
36
 
37
37
  @staticmethod
38
38
  def toolkit_config_schema() -> BaseModel:
39
39
  selected_tools = {x['name']: x['args_schema'].schema() for x in ZephyrScaleApiWrapper.model_construct().get_available_tools()}
40
- ZephyrScaleToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
41
40
  return create_model(
42
41
  name,
43
- max_results=(int, Field(default=100, description="Results count to show")),
42
+ max_results=(int, Field(default=100, description="Results count to show", gt=0)),
44
43
  zephyr_configuration=(ZephyrConfiguration, Field(description="Zephyr Configuration",
45
44
  json_schema_extra={'configuration_types': ['zephyr']})),
46
45
  pgvector_configuration=(Optional[PgVectorConfiguration], Field(default=None, description="PgVector Configuration",
@@ -75,18 +74,22 @@ class ZephyrScaleToolkit(BaseToolkit):
75
74
  **(kwargs.get('pgvector_configuration') or {}),
76
75
  }
77
76
  zephyr_wrapper = ZephyrScaleApiWrapper(**wrapper_payload)
78
- prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
79
77
  available_tools = zephyr_wrapper.get_available_tools()
80
78
  tools = []
81
79
  for tool in available_tools:
82
80
  if selected_tools:
83
81
  if tool["name"] not in selected_tools:
84
82
  continue
83
+ description = tool["description"]
84
+ if toolkit_name:
85
+ description = f"Toolkit: {toolkit_name}\n{description}"
86
+ description = description[:1000]
85
87
  tools.append(BaseAction(
86
88
  api_wrapper=zephyr_wrapper,
87
- name=prefix + tool["name"],
88
- description=tool["description"],
89
- args_schema=tool["args_schema"]
89
+ name=tool["name"],
90
+ description=description,
91
+ args_schema=tool["args_schema"],
92
+ metadata={TOOLKIT_NAME_META: toolkit_name, TOOLKIT_TYPE_META: name, TOOL_NAME_META: tool["name"]} if toolkit_name else {TOOL_NAME_META: tool["name"]}
90
93
  ))
91
94
  return cls(tools=tools)
92
95
 
@@ -177,13 +177,13 @@ ZephyrSearchTestCases = create_model(
177
177
  "ZephyrSearchTestCases",
178
178
  project_key=(str, Field(description="Jira project key filter")),
179
179
  search_term=(Optional[str], Field(description="Optional search term to filter test cases", default=None)),
180
- max_results=(Optional[int], Field(description="Maximum number of results to query from the API", default=1000)),
180
+ max_results=(Optional[int], Field(description="Maximum number of results to query from the API", default=1000, gt=0)),
181
181
  start_at=(Optional[int], Field(description="Zero-indexed starting position", default=0)),
182
182
  order_by=(Optional[str], Field(description="Field to order results by", default="name")),
183
183
  order_direction=(Optional[str], Field(description="Order direction", default="ASC")),
184
184
  archived=(Optional[bool], Field(description="Include archived test cases", default=False)),
185
185
  fields=(Optional[List[str]], Field(description="Fields to include in the response (default: key, name). Regular fields include key, name, id, labels, folder, etc. Custom fields can be included in the following ways:Individual custom fields via customFields.field_name format, All custom fields via customFields in the fields list", default=["key", "name"])),
186
- limit_results=(Optional[int], Field(description="Maximum number of filtered results to return", default=10)),
186
+ limit_results=(Optional[int], Field(description="Maximum number of filtered results to return", default=10, gt=0)),
187
187
  folder_id=(Optional[str], Field(description="Filter test cases by folder ID", default=None)),
188
188
  folder_name=(Optional[str], Field(description="Filter test cases by folder name (full or partial)", default=None)),
189
189
  exact_folder_match=(Optional[bool], Field(description="Whether to match the folder name exactly or allow partial matches", default=False)),
@@ -6,7 +6,8 @@ from pydantic import create_model, BaseModel, Field, SecretStr
6
6
  from .api_wrapper import ZephyrSquadApiWrapper
7
7
  from ..base.tool import BaseAction
8
8
  from ..elitea_base import filter_missconfigured_index_tools
9
- from ..utils import clean_string, TOOLKIT_SPLITTER, get_max_toolkit_length
9
+ from ..utils import clean_string, get_max_toolkit_length
10
+ from ...runtime.utils.constants import TOOLKIT_NAME_META, TOOL_NAME_META, TOOLKIT_TYPE_META
10
11
 
11
12
  name = "zephyr_squad"
12
13
 
@@ -21,12 +22,10 @@ def get_tools(tool):
21
22
 
22
23
  class ZephyrSquadToolkit(BaseToolkit):
23
24
  tools: List[BaseTool] = []
24
- toolkit_max_length: int = 0
25
25
 
26
26
  @staticmethod
27
27
  def toolkit_config_schema() -> BaseModel:
28
28
  selected_tools = {x['name']: x['args_schema'].schema() for x in ZephyrSquadApiWrapper.model_construct().get_available_tools()}
29
- ZephyrSquadToolkit.toolkit_max_length = get_max_toolkit_length(selected_tools)
30
29
  return create_model(
31
30
  name,
32
31
  account_id=(str, Field(description="AccountID for the user that is going to be authenticating")),
@@ -43,18 +42,22 @@ class ZephyrSquadToolkit(BaseToolkit):
43
42
  @filter_missconfigured_index_tools
44
43
  def get_toolkit(cls, selected_tools: list[str] | None = None, toolkit_name: Optional[str] = None, **kwargs):
45
44
  zephyr_api_wrapper = ZephyrSquadApiWrapper(**kwargs)
46
- prefix = clean_string(toolkit_name, cls.toolkit_max_length) + TOOLKIT_SPLITTER if toolkit_name else ''
47
45
  available_tools = zephyr_api_wrapper.get_available_tools()
48
46
  tools = []
49
47
  for tool in available_tools:
50
48
  if selected_tools:
51
49
  if tool["name"] not in selected_tools:
52
50
  continue
51
+ description = tool["description"]
52
+ if toolkit_name:
53
+ description = f"Toolkit: {toolkit_name}\n{description}"
54
+ description = description[:1000]
53
55
  tools.append(BaseAction(
54
56
  api_wrapper=zephyr_api_wrapper,
55
- name=prefix + tool["name"],
56
- description=tool["description"],
57
- args_schema=tool["args_schema"]
57
+ name=tool["name"],
58
+ description=description,
59
+ args_schema=tool["args_schema"],
60
+ metadata={TOOLKIT_NAME_META: toolkit_name, TOOLKIT_TYPE_META: name, TOOL_NAME_META: tool["name"]} if toolkit_name else {TOOL_NAME_META: tool["name"]}
58
61
  ))
59
62
  return cls(tools=tools)
60
63
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alita_sdk
3
- Version: 0.3.379
3
+ Version: 0.3.627
4
4
  Summary: SDK for building langchain agents using resources from Alita
5
5
  Author-email: Artem Rozumenko <artyom.rozumenko@gmail.com>, Mikalai Biazruchka <mikalai_biazruchka@epam.com>, Roman Mitusov <roman_mitusov@epam.com>, Ivan Krakhmaliuk <lifedj27@gmail.com>, Artem Dubrovskiy <ad13box@gmail.com>
6
6
  License-Expression: Apache-2.0
@@ -18,19 +18,20 @@ Requires-Dist: python-dotenv~=1.0.1
18
18
  Requires-Dist: jinja2~=3.1.3
19
19
  Requires-Dist: pillow~=11.1.0
20
20
  Requires-Dist: requests~=2.3
21
- Requires-Dist: pydantic~=2.10.0
21
+ Requires-Dist: pydantic~=2.12.0
22
22
  Requires-Dist: chardet==5.2.0
23
23
  Requires-Dist: fastapi==0.115.9
24
24
  Requires-Dist: httpcore==1.0.7
25
25
  Requires-Dist: urllib3>=2
26
26
  Requires-Dist: certifi==2024.8.30
27
+ Requires-Dist: aiohttp>=3.9.0
27
28
  Provides-Extra: runtime
28
29
  Requires-Dist: streamlit>=1.28.0; extra == "runtime"
29
30
  Requires-Dist: langchain_core<0.4.0,>=0.3.76; extra == "runtime"
30
31
  Requires-Dist: langchain<0.4.0,>=0.3.22; extra == "runtime"
31
32
  Requires-Dist: langchain_community<0.4.0,>=0.3.7; extra == "runtime"
32
33
  Requires-Dist: langchain-openai<0.4.0,>=0.3.0; extra == "runtime"
33
- Requires-Dist: langchain-anthropic<0.4.0,>=0.3.10; extra == "runtime"
34
+ Requires-Dist: langchain-anthropic<0.4.0,>=0.3.20; extra == "runtime"
34
35
  Requires-Dist: anthropic>=0.57.0; extra == "runtime"
35
36
  Requires-Dist: langgraph<0.5,>=0.4.8; extra == "runtime"
36
37
  Requires-Dist: langgraph-prebuilt==0.5.2; extra == "runtime"
@@ -67,12 +68,13 @@ Requires-Dist: pytesseract==0.3.13; extra == "runtime"
67
68
  Requires-Dist: markdown==3.5.1; extra == "runtime"
68
69
  Requires-Dist: beautifulsoup4==4.12.2; extra == "runtime"
69
70
  Requires-Dist: charset_normalizer==3.3.2; extra == "runtime"
70
- Requires-Dist: opentelemetry-exporter-otlp-proto-grpc==1.25.0; extra == "runtime"
71
- Requires-Dist: opentelemetry_api==1.25.0; extra == "runtime"
72
- Requires-Dist: opentelemetry_instrumentation==0.46b0; extra == "runtime"
73
- Requires-Dist: grpcio_status==1.63.0rc1; extra == "runtime"
74
- Requires-Dist: protobuf==4.25.7; extra == "runtime"
71
+ Requires-Dist: opentelemetry-exporter-otlp-proto-grpc>=1.25.0; extra == "runtime"
72
+ Requires-Dist: opentelemetry_api>=1.25.0; extra == "runtime"
73
+ Requires-Dist: opentelemetry_instrumentation>=0.46b0; extra == "runtime"
74
+ Requires-Dist: grpcio_status>=1.63.0rc1; extra == "runtime"
75
+ Requires-Dist: protobuf>=4.25.7; extra == "runtime"
75
76
  Requires-Dist: langchain-sandbox>=0.0.6; extra == "runtime"
77
+ Requires-Dist: langchain-mcp-adapters<0.2.0,>=0.1.14; extra == "runtime"
76
78
  Provides-Extra: tools
77
79
  Requires-Dist: dulwich==0.21.6; extra == "tools"
78
80
  Requires-Dist: paramiko==3.3.1; extra == "tools"
@@ -133,6 +135,7 @@ Provides-Extra: community
133
135
  Requires-Dist: retry-extended==0.2.3; extra == "community"
134
136
  Requires-Dist: pyobjtojson==0.3; extra == "community"
135
137
  Requires-Dist: elitea-analyse==0.1.2; extra == "community"
138
+ Requires-Dist: networkx>=3.0; extra == "community"
136
139
  Provides-Extra: all
137
140
  Requires-Dist: alita-sdk[runtime]; extra == "all"
138
141
  Requires-Dist: alita-sdk[tools]; extra == "all"
@@ -143,6 +146,11 @@ Requires-Dist: pytest-cov; extra == "dev"
143
146
  Requires-Dist: black; extra == "dev"
144
147
  Requires-Dist: flake8; extra == "dev"
145
148
  Requires-Dist: mypy; extra == "dev"
149
+ Provides-Extra: cli
150
+ Requires-Dist: click>=8.1.0; extra == "cli"
151
+ Requires-Dist: rich>=13.0.0; extra == "cli"
152
+ Requires-Dist: pyyaml>=6.0; extra == "cli"
153
+ Requires-Dist: langchain-mcp-adapters; extra == "cli"
146
154
  Dynamic: license-file
147
155
 
148
156
  Alita SDK
@@ -200,6 +208,144 @@ PROJECT_ID=<your_project_id>
200
208
  NOTE: these variables can be grabbed from your Elitea platform configuration page.
201
209
  ![Platform configuration](docs/readme_imgs/platform_config.png "Platform configuration")
202
210
 
211
+ ### Custom .env File Location
212
+
213
+ By default, the CLI looks for `.env` files in the following order:
214
+ 1. `.alita/.env` (recommended)
215
+ 2. `.env` in the current directory
216
+
217
+ You can override this by setting the `ALITA_ENV_FILE` environment variable:
218
+
219
+ ```bash
220
+ export ALITA_ENV_FILE=/path/to/your/.env
221
+ alita-cli agent chat
222
+ ```
223
+
224
+ Using the CLI for Interactive Chat
225
+ ----------------------------------
226
+
227
+ The Alita SDK includes a powerful CLI for interactive agent chat sessions.
228
+
229
+ ### Starting a Chat Session
230
+
231
+ ```bash
232
+ # Interactive selection (shows all available agents + direct chat option)
233
+ alita-cli agent chat
234
+
235
+ # Chat with a specific local agent
236
+ alita-cli agent chat .alita/agents/my-agent.agent.md
237
+
238
+ # Chat with a platform agent
239
+ alita-cli agent chat my-agent-name
240
+ ```
241
+
242
+ ### Direct Chat Mode (No Agent)
243
+
244
+ You can start a chat session directly with the LLM without any agent configuration:
245
+
246
+ ```bash
247
+ alita-cli agent chat
248
+ # Select option 1: "Direct chat with model (no agent)"
249
+ ```
250
+
251
+ This is useful for quick interactions or testing without setting up an agent.
252
+
253
+ ### Chat Commands
254
+
255
+ During a chat session, you can use the following commands:
256
+
257
+ | Command | Description |
258
+ |---------|-------------|
259
+ | `/help` | Show all available commands |
260
+ | `/model` | Switch to a different model (preserves chat history) |
261
+ | `/add_mcp` | Add an MCP server from your local mcp.json (preserves chat history) |
262
+ | `/add_toolkit` | Add a toolkit from $ALITA_DIR/tools (preserves chat history) |
263
+ | `/clear` | Clear conversation history |
264
+ | `/history` | Show conversation history |
265
+ | `/save` | Save conversation to file |
266
+ | `exit` | End conversation |
267
+
268
+ ### Enhanced Input Features
269
+
270
+ The chat interface includes readline-based input enhancements:
271
+
272
+ | Feature | Key/Action |
273
+ |---------|------------|
274
+ | **Tab completion** | Press `Tab` to autocomplete commands (e.g., `/mo` → `/model`) |
275
+ | **Command history** | `↑` / `↓` arrows to navigate through previous messages |
276
+ | **Cursor movement** | `←` / `→` arrows to move within the current line |
277
+ | **Start of line** | `Ctrl+A` jumps to the beginning of the line |
278
+ | **End of line** | `Ctrl+E` jumps to the end of the line |
279
+ | **Delete word** | `Ctrl+W` deletes the word before cursor |
280
+ | **Clear line** | `Ctrl+U` clears from cursor to beginning of line |
281
+
282
+ ### Dynamic Model Switching
283
+
284
+ Use `/model` to switch models on the fly:
285
+
286
+ ```
287
+ > /model
288
+
289
+ 🔧 Select a model:
290
+
291
+ # Model Type
292
+ 1 gpt-4o openai
293
+ 2 gpt-4o-mini openai
294
+ 3 claude-3-sonnet anthropic
295
+
296
+ Select model number: 1
297
+
298
+ ✓ Selected: gpt-4o
299
+ ╭──────────────────────────────────────────────────────────────╮
300
+ │ ℹ Model switched to gpt-4o. Agent state reset, chat history │
301
+ │ preserved. │
302
+ ╰──────────────────────────────────────────────────────────────╯
303
+ ```
304
+
305
+ ### Adding MCP Servers Dynamically
306
+
307
+ Use `/add_mcp` to add MCP servers during a chat session. Servers are loaded from your local `mcp.json` file (typically at `.alita/mcp.json`):
308
+
309
+ ```
310
+ > /add_mcp
311
+
312
+ 🔌 Select an MCP server to add:
313
+
314
+ # Server Type Command/URL
315
+ 1 playwright stdio npx @playwright/mcp@latest
316
+ 2 filesystem stdio npx @anthropic/mcp-fs
317
+
318
+ Select MCP server number: 1
319
+
320
+ ✓ Selected: playwright
321
+ ╭──────────────────────────────────────────────────────────────╮
322
+ │ ℹ Added MCP: playwright. Agent state reset, chat history │
323
+ │ preserved. │
324
+ ╰──────────────────────────────────────────────────────────────╯
325
+ ```
326
+
327
+ ### Adding Toolkits Dynamically
328
+
329
+ Use `/add_toolkit` to add toolkits from your `$ALITA_DIR/tools` directory (default: `.alita/tools`):
330
+
331
+ ```
332
+ > /add_toolkit
333
+
334
+ 🧰 Select a toolkit to add:
335
+
336
+ # Toolkit Type File
337
+ 1 jira jira jira-config.json
338
+ 2 github github github-config.json
339
+
340
+ Select toolkit number: 1
341
+
342
+ ✓ Selected: jira
343
+ ╭──────────────────────────────────────────────────────────────╮
344
+ │ ℹ Added toolkit: jira. Agent state reset, chat history │
345
+ │ preserved. │
346
+ ╰──────────────────────────────────────────────────────────────╯
347
+ ```
348
+
203
349
 
204
350
 
205
351
  Using SDK with Streamlit for Local Development