alita-sdk 0.3.418__py3-none-any.whl → 0.3.420__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.
@@ -138,6 +138,7 @@ def create_state(data: Optional[dict] = None):
138
138
  for key, value in data.items():
139
139
  # support of old & new UI
140
140
  value = value['type'] if isinstance(value, dict) else value
141
+ value = 'str' if value == 'string' else value # normalize string type (old state support)
141
142
  if key == 'messages':
142
143
  state_dict[key] = Annotated[list[AnyMessage], add_messages]
143
144
  elif value in ['str', 'int', 'float', 'bool', 'list', 'dict', 'number', 'dict']:
@@ -184,7 +185,7 @@ def propagate_the_input_mapping(input_mapping: dict[str, dict], input_variables:
184
185
  logger.error(f"KeyError in fstring formatting for key '{key}'. Attempt to find proper data in state.\n{e}")
185
186
  try:
186
187
  # search for variables in state if not found in var_dict
187
- input_data[key] = value['value'].format(**state)
188
+ input_data[key] = safe_format(value['value'], state)
188
189
  except KeyError as no_var_exception:
189
190
  logger.error(f"KeyError in fstring formatting for key '{key}' with state data.\n{no_var_exception}")
190
191
  # leave value as is if still not found (could be a constant string marked as fstring by mistake)
@@ -195,6 +196,13 @@ def propagate_the_input_mapping(input_mapping: dict[str, dict], input_variables:
195
196
  input_data[key] = source.get(value['value'], "")
196
197
  return input_data
197
198
 
199
+ def safe_format(template, mapping):
200
+ """Format a template string using a mapping, leaving placeholders unchanged if keys are missing."""
201
+
202
+ def replacer(match):
203
+ key = match.group(1)
204
+ return str(mapping.get(key, f'{{{key}}}'))
205
+ return re.sub(r'\{(\w+)\}', replacer, template)
198
206
 
199
207
  def create_pydantic_model(model_name: str, variables: dict[str, dict]):
200
208
  fields = {}
@@ -91,6 +91,10 @@ class LLMNode(BaseTool):
91
91
  f"Actual params: {func_args}")
92
92
  # cast to str in case user passes variable different from str
93
93
  messages = [SystemMessage(content=str(func_args.get('system'))), *func_args.get('chat_history', []), HumanMessage(content=str(func_args.get('task')))]
94
+ # Remove pre-last item if last two messages are same type and content
95
+ if len(messages) >= 2 and type(messages[-1]) == type(messages[-2]) and messages[-1].content == messages[
96
+ -2].content:
97
+ messages.pop(-2)
94
98
  else:
95
99
  # Flow for chat-based LLM node w/o prompt/task from pipeline but with messages in state
96
100
  # verify messages structure
@@ -329,11 +329,14 @@ class AzureDevOpsApiWrapper(NonCodeIndexerToolkit):
329
329
  parsed_item.update(fields_data)
330
330
 
331
331
  # extract relations if any
332
- relations_data = work_item.relations
332
+ relations_data = None
333
+ if expand and str(expand).lower() in ("relations", "all"):
334
+ try:
335
+ relations_data = getattr(work_item, 'relations', None)
336
+ except KeyError:
337
+ relations_data = None
333
338
  if relations_data:
334
- parsed_item['relations'] = []
335
- for relation in relations_data:
336
- parsed_item['relations'].append(relation.as_dict())
339
+ parsed_item['relations'] = [relation.as_dict() for relation in relations_data]
337
340
 
338
341
  if parse_attachments:
339
342
  # describe images in work item fields if present
@@ -344,13 +347,19 @@ class AzureDevOpsApiWrapper(NonCodeIndexerToolkit):
344
347
  for img in images:
345
348
  src = img.get('src')
346
349
  if src:
347
- description = self.parse_attachment_by_url(src, image_description_prompt)
350
+ description = self.parse_attachment_by_url(src, image_description_prompt=image_description_prompt)
348
351
  img['image-description'] = description
349
352
  parsed_item[field_name] = str(soup)
350
353
  # parse attached documents if present
351
- if parsed_item['relations']:
352
- for attachment in parsed_item['relations']:
353
- attachment['content'] = self.parse_attachment_by_url(attachment['url'], attachment['attributes']['name'], image_description_prompt)
354
+ for relation in parsed_item.get('relations', []):
355
+ # Only process actual file attachments
356
+ if relation.get('rel') == 'AttachedFile':
357
+ file_name = relation.get('attributes', {}).get('name')
358
+ if file_name:
359
+ try:
360
+ relation['content'] = self.parse_attachment_by_url(relation['url'], file_name, image_description_prompt=image_description_prompt)
361
+ except Exception as att_e:
362
+ logger.warning(f"Failed to parse attachment {file_name}: {att_e}")
354
363
 
355
364
 
356
365
  return parsed_item
@@ -474,9 +474,10 @@ class BaseIndexerToolkit(VectorStoreWrapperBase):
474
474
  "index_configuration": index_configuration,
475
475
  "created_on": created_on,
476
476
  "updated_on": created_on,
477
- "history": "[]",
478
477
  "task_id": None,
478
+ "conversation_id": None,
479
479
  }
480
+ metadata["history"] = json.dumps([metadata])
480
481
  index_meta_doc = Document(page_content=f"{IndexerKeywords.INDEX_META_TYPE.value}_{index_name}", metadata=metadata)
481
482
  add_documents(vectorstore=self.vectorstore, documents=[index_meta_doc])
482
483
 
@@ -489,6 +490,20 @@ class BaseIndexerToolkit(VectorStoreWrapperBase):
489
490
  metadata["indexed"] = result
490
491
  metadata["state"] = state
491
492
  metadata["updated_on"] = time.time()
493
+ #
494
+ history_raw = metadata.pop("history", "[]")
495
+ try:
496
+ history = json.loads(history_raw) if history_raw.strip() else []
497
+ # replace the last history item with updated metadata
498
+ if history and isinstance(history, list):
499
+ history[-1] = metadata
500
+ else:
501
+ history = [metadata]
502
+ except (json.JSONDecodeError, TypeError):
503
+ logger.warning(f"Failed to load index history: {history_raw}. Create new with only current item.")
504
+ history = [metadata]
505
+ #
506
+ metadata["history"] = json.dumps(history)
492
507
  index_meta_doc = Document(page_content=index_meta_raw.get("content", ""), metadata=metadata)
493
508
  add_documents(vectorstore=self.vectorstore, documents=[index_meta_doc], ids=[index_meta_raw.get("id")])
494
509
 
@@ -1,6 +1,7 @@
1
1
  import json
2
2
  import re
3
3
  import logging
4
+ import yaml
4
5
  from typing import List, Any, Optional, Dict
5
6
  from langchain_core.tools import BaseTool, BaseToolkit, ToolException
6
7
  from requests_openapi import Operation, Client, Server
@@ -101,7 +102,15 @@ class AlitaOpenAPIToolkit(BaseToolkit):
101
102
  else:
102
103
  tools_set = {}
103
104
  if isinstance(openapi_spec, str):
104
- openapi_spec = json.loads(openapi_spec)
105
+ # Try to detect if it's YAML or JSON by attempting to parse as JSON first
106
+ try:
107
+ openapi_spec = json.loads(openapi_spec)
108
+ except json.JSONDecodeError:
109
+ # If JSON parsing fails, try YAML
110
+ try:
111
+ openapi_spec = yaml.safe_load(openapi_spec)
112
+ except yaml.YAMLError as e:
113
+ raise ToolException(f"Failed to parse OpenAPI spec as JSON or YAML: {e}")
105
114
  c = Client()
106
115
  c.load_spec(openapi_spec)
107
116
  if headers:
@@ -92,15 +92,33 @@ class SharepointApiWrapper(NonCodeIndexerToolkit):
92
92
  target_list = self._client.web.lists.get_by_title(list_title)
93
93
  self._client.load(target_list)
94
94
  self._client.execute_query()
95
- items = target_list.items.get().top(limit).execute_query()
96
- logging.info("{0} items from sharepoint loaded successfully.".format(len(items)))
95
+ items = target_list.items.top(limit).get().execute_query()
96
+ logging.info("{0} items from sharepoint loaded successfully via SharePoint REST API.".format(len(items)))
97
97
  result = []
98
98
  for item in items:
99
99
  result.append(item.properties)
100
100
  return result
101
- except Exception as e:
102
- logging.error(f"Failed to load items from sharepoint: {e}")
103
- return ToolException("Can not list items. Please, double check List name and read permissions.")
101
+ except Exception as base_e:
102
+ logging.warning(f"Primary SharePoint REST list read failed: {base_e}. Attempting Graph API fallback.")
103
+ # Attempt Graph API fallback
104
+ try:
105
+ from .authorization_helper import SharepointAuthorizationHelper
106
+ auth_helper = SharepointAuthorizationHelper(
107
+ client_id=self.client_id,
108
+ client_secret=self.client_secret.get_secret_value() if self.client_secret else None,
109
+ tenant="", # optional for graph api (derived inside helper)
110
+ scope="", # optional for graph api
111
+ token_json="", # not needed for client credentials flow here
112
+ )
113
+ graph_items = auth_helper.get_list_items(self.site_url, list_title, limit)
114
+ if graph_items:
115
+ logging.info(f"{len(graph_items)} items from sharepoint loaded successfully via Graph API fallback.")
116
+ return graph_items
117
+ else:
118
+ return ToolException("List appears empty or inaccessible via both REST and Graph APIs.")
119
+ except Exception as graph_e:
120
+ logging.error(f"Graph API fallback failed: {graph_e}")
121
+ return ToolException(f"Cannot read list '{list_title}'. Check list name and permissions: {base_e} | {graph_e}")
104
122
 
105
123
 
106
124
  def get_files_list(self, folder_name: str = None, limit_files: int = 100):
@@ -185,3 +185,47 @@ class SharepointAuthorizationHelper:
185
185
  raise RuntimeError(f"File '{path}' not found in any private or shared documents.")
186
186
  except Exception as e:
187
187
  raise RuntimeError(f"Error in get_file_content: {e}")
188
+
189
+ def get_list_items(self, site_url: str, list_title: str, limit: int = 1000):
190
+ """Fallback Graph API method to read SharePoint list items by list title.
191
+
192
+ Returns a list of dictionaries representing list item fields.
193
+ """
194
+ if not site_url or not site_url.startswith("https://"):
195
+ raise ValueError(f"Invalid site_url format: {site_url}")
196
+ try:
197
+ access_token, site_id = self.generate_token_and_site_id(site_url)
198
+ headers = {"Authorization": f"Bearer {access_token}"}
199
+ lists_url = f"https://graph.microsoft.com/v1.0/sites/{site_id}/lists"
200
+ response = requests.get(lists_url, headers=headers)
201
+ if response.status_code != 200:
202
+ raise RuntimeError(f"Lists request failed: {response.status_code} {response.text}")
203
+ lists_json = response.json()
204
+ lists = lists_json.get("value", [])
205
+ target_list = None
206
+ normalized_title = list_title.strip().lower()
207
+ for lst in lists:
208
+ # displayName is the user-visible title. name can differ (internal name)
209
+ display_name = (lst.get("displayName") or lst.get("name") or '').strip().lower()
210
+ if display_name == normalized_title:
211
+ target_list = lst
212
+ break
213
+ if not target_list:
214
+ raise RuntimeError(f"List '{list_title}' not found via Graph API.")
215
+ list_id = target_list.get('id')
216
+ if not list_id:
217
+ raise RuntimeError(f"List '{list_title}' missing id field.")
218
+ items_url = f"https://graph.microsoft.com/v1.0/sites/{site_id}/lists/{list_id}/items?expand=fields&$top={limit}"
219
+ items_response = requests.get(items_url, headers=headers)
220
+ if items_response.status_code != 200:
221
+ raise RuntimeError(f"List items request failed: {items_response.status_code} {items_response.text}")
222
+ items_json = items_response.json()
223
+ values = items_json.get('value', [])
224
+ result = []
225
+ for item in values:
226
+ fields = item.get('fields', {})
227
+ if fields:
228
+ result.append(fields)
229
+ return result
230
+ except Exception as e:
231
+ raise RuntimeError(f"Error in get_list_items: {e}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alita_sdk
3
- Version: 0.3.418
3
+ Version: 0.3.420
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
@@ -49,7 +49,7 @@ alita_sdk/runtime/langchain/langraph_agent.py,sha256=9ezh0iDTQwyE4PBH96k9g31Mz2Y
49
49
  alita_sdk/runtime/langchain/mixedAgentParser.py,sha256=M256lvtsL3YtYflBCEp-rWKrKtcY1dJIyRGVv7KW9ME,2611
50
50
  alita_sdk/runtime/langchain/mixedAgentRenderes.py,sha256=asBtKqm88QhZRILditjYICwFVKF5KfO38hu2O-WrSWE,5964
51
51
  alita_sdk/runtime/langchain/store_manager.py,sha256=i8Fl11IXJhrBXq1F1ukEVln57B1IBe-tqSUvfUmBV4A,2218
52
- alita_sdk/runtime/langchain/utils.py,sha256=GxqG1xhdUd6BC01ZZFkdc_0Q27LNgc-mr6t_1LD7GRU,7579
52
+ alita_sdk/runtime/langchain/utils.py,sha256=GnHC3TzOrrrPtrSO2d_4WIevUXbd06hrHZ3l9ckvhQc,7980
53
53
  alita_sdk/runtime/langchain/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
54
  alita_sdk/runtime/langchain/agents/xml_chat.py,sha256=Mx7PK5T97_GrFCwHHZ3JZP42S7MwtUzV0W-_8j6Amt8,6212
55
55
  alita_sdk/runtime/langchain/document_loaders/AlitaBDDScenariosLoader.py,sha256=4kFU1ijrM1Jw7cywQv8mUiBHlE6w-uqfzSZP4hUV5P4,3771
@@ -114,7 +114,7 @@ alita_sdk/runtime/tools/function.py,sha256=VOgcCjsDfyH2kBbX4k3DtwpsW7aX0JETahC26
114
114
  alita_sdk/runtime/tools/graph.py,sha256=7jImBBSEdP5Mjnn2keOiyUwdGDFhEXLUrgUiugO3mgA,3503
115
115
  alita_sdk/runtime/tools/image_generation.py,sha256=Kls9D_ke_SK7xmVr7I9SlQcAEBJc86gf66haN0qIj9k,7469
116
116
  alita_sdk/runtime/tools/indexer_tool.py,sha256=whSLPevB4WD6dhh2JDXEivDmTvbjiMV1MrPl9cz5eLA,4375
117
- alita_sdk/runtime/tools/llm.py,sha256=Oq0IH1mVEgtkw-8p5y-_xTCz-OcWtfvtR5xl19Anrhc,15875
117
+ alita_sdk/runtime/tools/llm.py,sha256=iRG_wU4T01LRsjEMPZe5Uah7LiMqDc-vspwkMuQtltk,16136
118
118
  alita_sdk/runtime/tools/loop.py,sha256=uds0WhZvwMxDVFI6MZHrcmMle637cQfBNg682iLxoJA,8335
119
119
  alita_sdk/runtime/tools/loop_output.py,sha256=U4hO9PCQgWlXwOq6jdmCGbegtAxGAPXObSxZQ3z38uk,8069
120
120
  alita_sdk/runtime/tools/mcp_server_tool.py,sha256=MhLxZJ44LYrB_0GrojmkyqKoDRaqIHkEQAsg718ipog,4277
@@ -136,7 +136,7 @@ alita_sdk/runtime/utils/toolkit_runtime.py,sha256=MU63Fpxj0b5_r1IUUc0Q3-PN9VwL7r
136
136
  alita_sdk/runtime/utils/toolkit_utils.py,sha256=I9QFqnaqfVgN26LUr6s3XlBlG6y0CoHURnCzG7XcwVs,5311
137
137
  alita_sdk/runtime/utils/utils.py,sha256=PJK8A-JVIzY1IowOjGG8DIqsIiEFe65qDKvFcjJCKWA,1041
138
138
  alita_sdk/tools/__init__.py,sha256=wrcSP0AN6HukZHPXpObCKI58cY0lVpHyzbpq609CMhE,10726
139
- alita_sdk/tools/base_indexer_toolkit.py,sha256=7UTcrmvGvmIBF3WGKrsEp7zJL-XB1JIgaRkbE1ZSS9A,26439
139
+ alita_sdk/tools/base_indexer_toolkit.py,sha256=hK1Q2dvNctZCw2K1-khlQrR1Q0JDQviZjqDUiqpnazg,27180
140
140
  alita_sdk/tools/code_indexer_toolkit.py,sha256=2VkOC8JfBDc25_jp-NWyMYqpaYRETIzTJFLrIYrfBpE,7814
141
141
  alita_sdk/tools/elitea_base.py,sha256=34fmVdYgd2YXifU5LFNjMQysr4OOIZ6AOZjq4GxLgSw,34417
142
142
  alita_sdk/tools/non_code_indexer_toolkit.py,sha256=6Lrqor1VeSLbPLDHAfg_7UAUqKFy1r_n6bdsc4-ak98,1315
@@ -149,7 +149,7 @@ alita_sdk/tools/ado/test_plan/test_plan_wrapper.py,sha256=MHM1WJUUWIgOUxGPjQUhNU
149
149
  alita_sdk/tools/ado/wiki/__init__.py,sha256=ela6FOuT1fqN3FvHGBflzAh16HS1SSPsJYS2SldRX7A,5272
150
150
  alita_sdk/tools/ado/wiki/ado_wrapper.py,sha256=qqKJw755X-kgB2KkcwFECa464xLKmlKrhqKfZ5Da5Gs,18188
151
151
  alita_sdk/tools/ado/work_item/__init__.py,sha256=jml_zSkdC7gdGIoX2ZqRgDb45nhT3ZWzNsZ0II0iVJI,5474
152
- alita_sdk/tools/ado/work_item/ado_wrapper.py,sha256=LTZl9yiqjsoKdy-6zD4as3NCZg1NY1Ogp9LQbiV-IZw,30851
152
+ alita_sdk/tools/ado/work_item/ado_wrapper.py,sha256=uURYPFEj2kVa-mxgaa6duQ0RRwUQTi4yBopdmHeiMPQ,31420
153
153
  alita_sdk/tools/advanced_jira_mining/__init__.py,sha256=GdrFVsyG8h43BnQwBKUtZ_ca_0atP1rQ_0adkd9mssc,4703
154
154
  alita_sdk/tools/advanced_jira_mining/data_mining_wrapper.py,sha256=nZPtuwVWp8VeHw1B8q9kdwf-6ZvHnlXTOGdcIMDkKpw,44211
155
155
  alita_sdk/tools/aws/__init__.py,sha256=tB6GCOg4XGSpR6qgbgAF4MUQ5-YmQCbWurWgrVKEKQ8,181
@@ -277,7 +277,7 @@ alita_sdk/tools/memory/__init__.py,sha256=aOF0-PAAqBZS3rI2IOezyLhZpn-WpV--ABy4J_
277
277
  alita_sdk/tools/ocr/__init__.py,sha256=pvslKVXyJmK0q23FFDNieuc7RBIuzNXTjTNj-GqhGb0,3335
278
278
  alita_sdk/tools/ocr/api_wrapper.py,sha256=08UF8wj1sR8DcW0z16pw19bgLatLkBF8dySW-Ds8iRk,29649
279
279
  alita_sdk/tools/ocr/text_detection.py,sha256=1DBxt54r3_HdEi93QynSIVta3rH3UpIvy799TPtDTtk,23825
280
- alita_sdk/tools/openapi/__init__.py,sha256=x1U4SGApL6MmNFz9SSsQCv352wMAIdGv0z4eMmYnjCw,4984
280
+ alita_sdk/tools/openapi/__init__.py,sha256=a3eE1zL2InB_bnngKhFoQlR-B4voywqs3s9mEbWypCE,5417
281
281
  alita_sdk/tools/pandas/__init__.py,sha256=rGenKJH5b9__qM4GerpyLT5YEhNk7W1gA7gn6Zpew04,2748
282
282
  alita_sdk/tools/pandas/api_wrapper.py,sha256=wn0bagB45Tz_kN0FoKUCIxKcYklMMWTqQP5NOM8_Kwc,11100
283
283
  alita_sdk/tools/pandas/dataframe/__init__.py,sha256=iOZRlYDEtwqg2MaYFFxETjN8yHAkUqSNe86cm6ao4LA,108
@@ -317,8 +317,8 @@ alita_sdk/tools/servicenow/__init__.py,sha256=ziEt2juPrGFyB98ZXbGf25v6gZo4UJTHsz
317
317
  alita_sdk/tools/servicenow/api_wrapper.py,sha256=WpH-bBLGFdhehs4g-K-WAkNuaD1CSrwsDpdgB3RG53s,6120
318
318
  alita_sdk/tools/servicenow/servicenow_client.py,sha256=Rdqfu-ll-qbnclMzChLZBsfXRDzgoX_FdeI2WLApWxc,3269
319
319
  alita_sdk/tools/sharepoint/__init__.py,sha256=5z2iSmm-0kbHKf70wN6OOgS4Px7tOzwkIpHXz0Vrbj4,4045
320
- alita_sdk/tools/sharepoint/api_wrapper.py,sha256=QcOtgc8L10YLdSK8LwACV_vRBF7T-u7T9-W05TbuAQI,15409
321
- alita_sdk/tools/sharepoint/authorization_helper.py,sha256=QvxWFBjYZfhI1h_KkSrDbRh8D5BlFX8xWDLmlIoO4mo,9569
320
+ alita_sdk/tools/sharepoint/api_wrapper.py,sha256=yOAZfa9-GcjohTak-TqcFL8f7s18hIA89FNO0qXjb_s,16614
321
+ alita_sdk/tools/sharepoint/authorization_helper.py,sha256=GN_UkI_HOn9b5UFlxqck7sm6HuB_Kh4wCIGBYFPe2dg,11924
322
322
  alita_sdk/tools/sharepoint/utils.py,sha256=CO1PNRC5CpQaVo2Gdenj_jqm2bReSqUT92Bk5s37d8M,573
323
323
  alita_sdk/tools/slack/__init__.py,sha256=YiPAoRc6y6uVpfHl0K1Qi-flcyPlWFIMVcVbhicGWXY,3990
324
324
  alita_sdk/tools/slack/api_wrapper.py,sha256=5VrV7iSGno8ZcDzEHdGPNhInhtODGPPvAzoZ9W9iQWE,14009
@@ -353,8 +353,8 @@ alita_sdk/tools/zephyr_scale/api_wrapper.py,sha256=kT0TbmMvuKhDUZc0i7KO18O38JM9S
353
353
  alita_sdk/tools/zephyr_squad/__init__.py,sha256=0ne8XLJEQSLOWfzd2HdnqOYmQlUliKHbBED5kW_Vias,2895
354
354
  alita_sdk/tools/zephyr_squad/api_wrapper.py,sha256=kmw_xol8YIYFplBLWTqP_VKPRhL_1ItDD0_vXTe_UuI,14906
355
355
  alita_sdk/tools/zephyr_squad/zephyr_squad_cloud_client.py,sha256=R371waHsms4sllHCbijKYs90C-9Yu0sSR3N4SUfQOgU,5066
356
- alita_sdk-0.3.418.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
357
- alita_sdk-0.3.418.dist-info/METADATA,sha256=rVvyl2LbdC2yBz1PsgmHzvzlew-bTpmmI6gpi-VOYYE,19071
358
- alita_sdk-0.3.418.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
359
- alita_sdk-0.3.418.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
360
- alita_sdk-0.3.418.dist-info/RECORD,,
356
+ alita_sdk-0.3.420.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
357
+ alita_sdk-0.3.420.dist-info/METADATA,sha256=AeXKBZovWOgn_XGXStvfBGyzRJ7_vubjwyKN57hf9P8,19071
358
+ alita_sdk-0.3.420.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
359
+ alita_sdk-0.3.420.dist-info/top_level.txt,sha256=0vJYy5p_jK6AwVb1aqXr7Kgqgk3WDtQ6t5C-XI9zkmg,10
360
+ alita_sdk-0.3.420.dist-info/RECORD,,