alita-sdk 0.3.458__py3-none-any.whl → 0.3.459__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.
@@ -0,0 +1,330 @@
1
+ """
2
+ Toolkit testing commands for Alita CLI.
3
+
4
+ Provides commands to list, inspect, and test toolkits directly from the command line.
5
+ """
6
+
7
+ import click
8
+ import json
9
+ import logging
10
+ from typing import Optional, Dict, Any
11
+
12
+ from .cli import get_client
13
+
14
+ logger = logging.getLogger(__name__)
15
+
16
+
17
+ @click.group()
18
+ def toolkit():
19
+ """Toolkit testing commands."""
20
+ pass
21
+
22
+
23
+ @toolkit.command('list')
24
+ @click.option('--failed', is_flag=True, help='Show failed imports')
25
+ @click.pass_context
26
+ def toolkit_list(ctx, failed: bool):
27
+ """List all available toolkits."""
28
+ formatter = ctx.obj['formatter']
29
+
30
+ try:
31
+ # Import toolkit registry
32
+ from alita_sdk.tools import AVAILABLE_TOOLS, AVAILABLE_TOOLKITS, FAILED_IMPORTS
33
+
34
+ if failed:
35
+ # Show failed imports
36
+ if FAILED_IMPORTS:
37
+ click.echo("\nFailed toolkit imports:\n")
38
+ for name, error in FAILED_IMPORTS.items():
39
+ click.echo(f" - {name}: {error}")
40
+ click.echo(f"\nTotal failed: {len(FAILED_IMPORTS)}")
41
+ else:
42
+ click.echo("\nNo failed imports")
43
+ return
44
+
45
+ # Build toolkit list
46
+ toolkits = []
47
+ for name, toolkit_dict in AVAILABLE_TOOLS.items():
48
+ toolkit_class_name = None
49
+ if 'toolkit_class' in toolkit_dict:
50
+ toolkit_class_name = toolkit_dict['toolkit_class'].__name__
51
+
52
+ toolkits.append({
53
+ 'name': name,
54
+ 'class_name': toolkit_class_name,
55
+ 'has_get_tools': 'get_tools' in toolkit_dict
56
+ })
57
+
58
+ # Format and display
59
+ output = formatter.format_toolkit_list(toolkits)
60
+ click.echo(output)
61
+
62
+ except Exception as e:
63
+ logger.exception("Failed to list toolkits")
64
+ click.echo(formatter.format_error(str(e)), err=True)
65
+ raise click.Abort()
66
+
67
+
68
+ @toolkit.command('schema')
69
+ @click.argument('toolkit_name')
70
+ @click.pass_context
71
+ def toolkit_schema(ctx, toolkit_name: str):
72
+ """
73
+ Show configuration schema for a toolkit.
74
+
75
+ TOOLKIT_NAME: Name of the toolkit (e.g., 'jira', 'github', 'confluence')
76
+ """
77
+ formatter = ctx.obj['formatter']
78
+
79
+ try:
80
+ # Import toolkit registry
81
+ from alita_sdk.tools import AVAILABLE_TOOLKITS
82
+
83
+ # Find toolkit class
84
+ toolkit_class = None
85
+ for name, cls in AVAILABLE_TOOLKITS.items():
86
+ if name.lower().replace('toolkit', '').replace('alita', '').strip() == toolkit_name.lower():
87
+ toolkit_class = cls
88
+ break
89
+
90
+ if not toolkit_class:
91
+ # Try direct match
92
+ for name, cls in AVAILABLE_TOOLKITS.items():
93
+ if toolkit_name.lower() in name.lower():
94
+ toolkit_class = cls
95
+ break
96
+
97
+ if not toolkit_class:
98
+ available = [name.lower().replace('toolkit', '').replace('alita', '').strip()
99
+ for name in AVAILABLE_TOOLKITS.keys()]
100
+ raise click.ClickException(
101
+ f"Toolkit '{toolkit_name}' not found.\n"
102
+ f"Available toolkits: {', '.join(sorted(set(available)))}"
103
+ )
104
+
105
+ # Get schema
106
+ schema_model = toolkit_class.toolkit_config_schema()
107
+ schema = schema_model.model_json_schema()
108
+
109
+ # Format and display
110
+ if formatter.__class__.__name__ == 'JSONFormatter':
111
+ output = formatter.format_toolkit_schema(toolkit_name, schema)
112
+ else:
113
+ output = formatter.format_toolkit_schema(toolkit_name, schema)
114
+
115
+ click.echo(output)
116
+
117
+ except click.ClickException:
118
+ raise
119
+ except Exception as e:
120
+ logger.exception(f"Failed to get schema for toolkit '{toolkit_name}'")
121
+ click.echo(formatter.format_error(str(e)), err=True)
122
+ raise click.Abort()
123
+
124
+
125
+ @toolkit.command('test')
126
+ @click.argument('toolkit_type')
127
+ @click.option('--tool', required=True, help='Tool name to execute')
128
+ @click.option('--config', 'config_file', type=click.File('r'),
129
+ help='Toolkit configuration JSON file')
130
+ @click.option('--params', type=click.File('r'),
131
+ help='Tool parameters JSON file')
132
+ @click.option('--param', multiple=True,
133
+ help='Tool parameter as key=value (can be used multiple times)')
134
+ @click.option('--llm-model', default='gpt-4o-mini',
135
+ help='LLM model to use (default: gpt-4o-mini)')
136
+ @click.option('--temperature', default=0.1, type=float,
137
+ help='LLM temperature (default: 0.1)')
138
+ @click.option('--max-tokens', default=1000, type=int,
139
+ help='LLM max tokens (default: 1000)')
140
+ @click.pass_context
141
+ def toolkit_test(ctx, toolkit_type: str, tool: str, config_file, params,
142
+ param, llm_model: str, temperature: float, max_tokens: int):
143
+ """
144
+ Test a specific tool from a toolkit.
145
+
146
+ TOOLKIT_TYPE: Type of toolkit (e.g., 'jira', 'github', 'confluence')
147
+
148
+ Examples:
149
+
150
+ # Test with config and params from files
151
+ alita-cli toolkit test jira --tool get_issue \\
152
+ --config jira-config.json --params params.json
153
+
154
+ # Test with inline parameters
155
+ alita-cli toolkit test jira --tool get_issue \\
156
+ --config jira-config.json --param issue_key=PROJ-123
157
+
158
+ # Test with JSON output for scripting
159
+ alita-cli --output json toolkit test github --tool get_issue \\
160
+ --config github-config.json --param owner=user --param repo=myrepo
161
+ """
162
+ formatter = ctx.obj['formatter']
163
+ client = get_client(ctx)
164
+
165
+ try:
166
+ # Load toolkit configuration
167
+ toolkit_config = {}
168
+ if config_file:
169
+ toolkit_config = json.load(config_file)
170
+ logger.debug(f"Loaded toolkit config from {config_file.name}")
171
+
172
+ # Load tool parameters
173
+ tool_params = {}
174
+ if params:
175
+ tool_params = json.load(params)
176
+ logger.debug(f"Loaded tool params from {params.name}")
177
+
178
+ # Parse inline parameters
179
+ if param:
180
+ for param_pair in param:
181
+ if '=' not in param_pair:
182
+ raise click.ClickException(
183
+ f"Invalid parameter format: '{param_pair}'. "
184
+ "Use --param key=value"
185
+ )
186
+ key, value = param_pair.split('=', 1)
187
+
188
+ # Try to parse as JSON for complex values
189
+ try:
190
+ tool_params[key] = json.loads(value)
191
+ except json.JSONDecodeError:
192
+ tool_params[key] = value
193
+
194
+ logger.debug(f"Parsed {len(param)} inline parameters")
195
+
196
+ # Prepare full toolkit configuration
197
+ full_config = {
198
+ 'toolkit_name': toolkit_type,
199
+ 'type': toolkit_type,
200
+ 'settings': toolkit_config
201
+ }
202
+
203
+ # LLM configuration
204
+ llm_config = {
205
+ 'temperature': temperature,
206
+ 'max_tokens': max_tokens,
207
+ 'top_p': 1.0
208
+ }
209
+
210
+ # Execute test
211
+ logger.info(f"Testing tool '{tool}' from toolkit '{toolkit_type}'")
212
+ result = client.test_toolkit_tool(
213
+ toolkit_config=full_config,
214
+ tool_name=tool,
215
+ tool_params=tool_params,
216
+ llm_model=llm_model,
217
+ llm_config=llm_config
218
+ )
219
+
220
+ # Format and display result
221
+ output = formatter.format_toolkit_result(result)
222
+ click.echo(output)
223
+
224
+ # Exit with error code if test failed
225
+ if not result.get('success', False):
226
+ raise click.Abort()
227
+
228
+ except click.ClickException:
229
+ raise
230
+ except Exception as e:
231
+ logger.exception("Failed to execute toolkit test")
232
+ click.echo(formatter.format_error(str(e)), err=True)
233
+ raise click.Abort()
234
+
235
+
236
+ @toolkit.command('tools')
237
+ @click.argument('toolkit_type')
238
+ @click.option('--config', 'config_file', type=click.File('r'),
239
+ help='Toolkit configuration JSON file (required for some toolkits)')
240
+ @click.pass_context
241
+ def toolkit_tools(ctx, toolkit_type: str, config_file):
242
+ """
243
+ List available tools for a specific toolkit.
244
+
245
+ TOOLKIT_TYPE: Type of toolkit (e.g., 'jira', 'github', 'confluence')
246
+
247
+ Some toolkits require configuration to determine available tools.
248
+ Use --config to provide configuration if needed.
249
+ """
250
+ formatter = ctx.obj['formatter']
251
+ client = get_client(ctx)
252
+
253
+ try:
254
+ # Load toolkit configuration if provided
255
+ toolkit_config = {}
256
+ if config_file:
257
+ toolkit_config = json.load(config_file)
258
+
259
+ # Import and instantiate toolkit
260
+ from alita_sdk.tools import AVAILABLE_TOOLS
261
+
262
+ if toolkit_type not in AVAILABLE_TOOLS:
263
+ raise click.ClickException(
264
+ f"Toolkit '{toolkit_type}' not found. "
265
+ f"Use 'alita-cli toolkit list' to see available toolkits."
266
+ )
267
+
268
+ toolkit_entry = AVAILABLE_TOOLS[toolkit_type]
269
+
270
+ if 'toolkit_class' not in toolkit_entry:
271
+ raise click.ClickException(
272
+ f"Toolkit '{toolkit_type}' does not support tool listing"
273
+ )
274
+
275
+ # Get toolkit class and instantiate
276
+ toolkit_class = toolkit_entry['toolkit_class']
277
+
278
+ # Create minimal configuration
279
+ full_config = {
280
+ 'toolkit_name': toolkit_type,
281
+ 'type': toolkit_type,
282
+ 'settings': toolkit_config
283
+ }
284
+
285
+ # Try to get available tools via API wrapper
286
+ try:
287
+ # Instantiate API wrapper if possible
288
+ api_wrapper_class = None
289
+
290
+ # Find API wrapper class by inspecting toolkit
291
+ import inspect
292
+ for name, obj in inspect.getmembers(toolkit_class):
293
+ if inspect.isclass(obj) and 'ApiWrapper' in obj.__name__:
294
+ api_wrapper_class = obj
295
+ break
296
+
297
+ if api_wrapper_class:
298
+ try:
299
+ api_wrapper = api_wrapper_class(**toolkit_config)
300
+ available_tools = api_wrapper.get_available_tools()
301
+
302
+ # Format tools list
303
+ click.echo(f"\nAvailable tools for {toolkit_type}:\n")
304
+ for tool_info in available_tools:
305
+ tool_name = tool_info.get('name', 'unknown')
306
+ description = tool_info.get('description', '')
307
+ click.echo(f" - {tool_name}")
308
+ if description:
309
+ click.echo(f" {description}")
310
+
311
+ click.echo(f"\nTotal: {len(available_tools)} tools")
312
+ return
313
+
314
+ except Exception as e:
315
+ logger.debug(f"Could not instantiate API wrapper: {e}")
316
+
317
+ # Fallback: show general info
318
+ click.echo(f"\n{toolkit_type} toolkit is available")
319
+ click.echo("Use 'alita-cli toolkit schema {toolkit_type}' to see configuration options")
320
+
321
+ except Exception as e:
322
+ logger.exception("Failed to list tools")
323
+ raise click.ClickException(str(e))
324
+
325
+ except click.ClickException:
326
+ raise
327
+ except Exception as e:
328
+ logger.exception("Failed to list toolkit tools")
329
+ click.echo(formatter.format_error(str(e)), err=True)
330
+ raise click.Abort()
@@ -34,7 +34,8 @@ class FunctionTool(BaseTool):
34
34
 
35
35
  del state_copy['messages'] # remove messages to avoid issues with pickling without langchain-core
36
36
  # inject state into the code block as alita_state variable
37
- pyodide_predata = f"#state dict\nalita_state = {state_copy}\n"
37
+ state_json = json.dumps(state_copy, ensure_ascii=False)
38
+ pyodide_predata = f'#state dict\nimport json\nalita_state = {repr(state_json)}\n'
38
39
  return pyodide_predata
39
40
 
40
41
  def _handle_pyodide_output(self, tool_result: Any) -> dict:
@@ -94,9 +95,7 @@ class FunctionTool(BaseTool):
94
95
  # special handler for PyodideSandboxTool
95
96
  if self._is_pyodide_tool():
96
97
  code = func_args['code']
97
- func_args['code'] = (f"{self._prepare_pyodide_input(state)}\n{code}"
98
- # handle new lines in the code properly
99
- .replace('\\n','\\\\n'))
98
+ func_args['code'] = f"{self._prepare_pyodide_input(state)}\n{code}"
100
99
  try:
101
100
  tool_result = self.tool.invoke(func_args, config, **kwargs)
102
101
  dispatch_custom_event(
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alita_sdk
3
- Version: 0.3.458
3
+ Version: 0.3.459
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
@@ -25,6 +25,10 @@ Requires-Dist: httpcore==1.0.7
25
25
  Requires-Dist: urllib3>=2
26
26
  Requires-Dist: certifi==2024.8.30
27
27
  Requires-Dist: aiohttp>=3.9.0
28
+ Provides-Extra: cli
29
+ Requires-Dist: click>=8.1.0; extra == "cli"
30
+ Requires-Dist: rich>=13.0.0; extra == "cli"
31
+ Requires-Dist: pyyaml>=6.0; extra == "cli"
28
32
  Provides-Extra: runtime
29
33
  Requires-Dist: streamlit>=1.28.0; extra == "runtime"
30
34
  Requires-Dist: langchain_core<0.4.0,>=0.3.76; extra == "runtime"
@@ -138,6 +142,7 @@ Provides-Extra: all
138
142
  Requires-Dist: alita-sdk[runtime]; extra == "all"
139
143
  Requires-Dist: alita-sdk[tools]; extra == "all"
140
144
  Requires-Dist: alita-sdk[community]; extra == "all"
145
+ Requires-Dist: alita-sdk[cli]; extra == "all"
141
146
  Provides-Extra: dev
142
147
  Requires-Dist: pytest; extra == "dev"
143
148
  Requires-Dist: pytest-cov; extra == "dev"
@@ -1,4 +1,11 @@
1
1
  alita_sdk/__init__.py,sha256=fxeNiqiVpIFAJls31Oomifyrtd5gT9iPUTdkWjDOB2Y,656
2
+ alita_sdk/cli/__init__.py,sha256=HiHHouMh0EHmK1qMVzvz6vfIOu8Pm6XXw0dd_hXZ288,278
3
+ alita_sdk/cli/__main__.py,sha256=dAhgWWWEOG1ZiwCs6wQoJwnD62cFRnxiyiAoiFqU8K4,420
4
+ alita_sdk/cli/agents.py,sha256=uMlKiWs85zExE7_Q6NBbw6frnUVK-Ei2KynIddMHXn0,42419
5
+ alita_sdk/cli/cli.py,sha256=k8jwaTKt3At9NfopOcp-BqXitqO0jcei1ACuyoUA9eY,4812
6
+ alita_sdk/cli/config.py,sha256=GiWe7K2RHC_PnH1nEUBodgi0d14oPbIdQhYl69Gbx1o,3978
7
+ alita_sdk/cli/formatting.py,sha256=ip95brhcFcx3Ub7PRLv1aDGniGW13RCGDgc1_8i9ZwM,6566
8
+ alita_sdk/cli/toolkit.py,sha256=IC1zCXiIRUh-swcBC5VhdREIaXGCu5-OfSWyGSUOx0Q,11693
2
9
  alita_sdk/community/__init__.py,sha256=8N7wWwPhoyOq3p8wlV3-pb3l3nJCR8TUrtV9iIPLU88,2523
3
10
  alita_sdk/community/utils.py,sha256=lvuCJaNqVPHOORJV6kIPcXJcdprVW_TJvERtYAEgpjM,249
4
11
  alita_sdk/configurations/__init__.py,sha256=3_MlzyzAi1dog6MFQD_ICOZvaPfXf2UfhSZwlF1knnw,3983
@@ -114,7 +121,7 @@ alita_sdk/runtime/tools/application.py,sha256=RCGe-mRfj8372gTFkEX2xBvcYhw7IKdU1t
114
121
  alita_sdk/runtime/tools/artifact.py,sha256=u3szFwZqguHrPZ3tZJ7S_TiZl7cxlT3oHYd6zbdpRDE,13842
115
122
  alita_sdk/runtime/tools/datasource.py,sha256=pvbaSfI-ThQQnjHG-QhYNSTYRnZB0rYtZFpjCfpzxYI,2443
116
123
  alita_sdk/runtime/tools/echo.py,sha256=spw9eCweXzixJqHnZofHE1yWiSUa04L4VKycf3KCEaM,486
117
- alita_sdk/runtime/tools/function.py,sha256=8KTMwut7BnruaVhgO2zFn9YvCU5bT7REQdpPV-SbHh8,6605
124
+ alita_sdk/runtime/tools/function.py,sha256=0O29IFs0ZupXxqXwGa4Pmm_QdxulUR3ZDGowXDPRgv8,6557
118
125
  alita_sdk/runtime/tools/graph.py,sha256=7jImBBSEdP5Mjnn2keOiyUwdGDFhEXLUrgUiugO3mgA,3503
119
126
  alita_sdk/runtime/tools/image_generation.py,sha256=Kls9D_ke_SK7xmVr7I9SlQcAEBJc86gf66haN0qIj9k,7469
120
127
  alita_sdk/runtime/tools/indexer_tool.py,sha256=whSLPevB4WD6dhh2JDXEivDmTvbjiMV1MrPl9cz5eLA,4375
@@ -361,8 +368,9 @@ alita_sdk/tools/zephyr_scale/api_wrapper.py,sha256=kT0TbmMvuKhDUZc0i7KO18O38JM9S
361
368
  alita_sdk/tools/zephyr_squad/__init__.py,sha256=Gl1YAFaMMufTNjIpnuo_c_lbDsQkmproYdZz2ZppgJ4,3007
362
369
  alita_sdk/tools/zephyr_squad/api_wrapper.py,sha256=kmw_xol8YIYFplBLWTqP_VKPRhL_1ItDD0_vXTe_UuI,14906
363
370
  alita_sdk/tools/zephyr_squad/zephyr_squad_cloud_client.py,sha256=R371waHsms4sllHCbijKYs90C-9Yu0sSR3N4SUfQOgU,5066
364
- alita_sdk-0.3.458.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
365
- alita_sdk-0.3.458.dist-info/METADATA,sha256=2rKUTBUSXzFWP9316T-IRjMtsAuwy-bvNtOOlkxOPLg,19101
366
- alita_sdk-0.3.458.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
367
- alita_sdk-0.3.458.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
368
- alita_sdk-0.3.458.dist-info/RECORD,,
371
+ alita_sdk-0.3.459.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
372
+ alita_sdk-0.3.459.dist-info/METADATA,sha256=7Oo76t6BYB0tv0jHbuloCQQrwMpcw7Ga_jqI1KVZeJ0,19298
373
+ alita_sdk-0.3.459.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
374
+ alita_sdk-0.3.459.dist-info/entry_points.txt,sha256=sSxsIZu9YjVGsgf-5mHC631FeBcT6f2vUjm0A_L9tcU,53
375
+ alita_sdk-0.3.459.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
376
+ alita_sdk-0.3.459.dist-info/RECORD,,
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ alita-cli = alita_sdk.cli.cli:main