alita-sdk 0.3.115__py3-none-any.whl → 0.3.117__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/community/analysis/jira_analyse/__init__.py +2 -4
- alita_sdk/community/analysis/jira_analyse/api_wrapper.py +27 -23
- alita_sdk/langchain/langraph_agent.py +80 -1
- alita_sdk/langchain/utils.py +1 -1
- alita_sdk/tools/router.py +35 -0
- alita_sdk/utils/AlitaCallback.py +32 -2
- {alita_sdk-0.3.115.dist-info → alita_sdk-0.3.117.dist-info}/METADATA +1 -1
- {alita_sdk-0.3.115.dist-info → alita_sdk-0.3.117.dist-info}/RECORD +11 -10
- {alita_sdk-0.3.115.dist-info → alita_sdk-0.3.117.dist-info}/WHEEL +1 -1
- {alita_sdk-0.3.115.dist-info → alita_sdk-0.3.117.dist-info}/licenses/LICENSE +0 -0
- {alita_sdk-0.3.115.dist-info → alita_sdk-0.3.117.dist-info}/top_level.txt +0 -0
@@ -90,10 +90,8 @@ class AnalyseJira(BaseToolkit):
|
|
90
90
|
jira_username = kwargs.get('jira_username')
|
91
91
|
jira_token = kwargs.get('jira_token')
|
92
92
|
jira_api_key = kwargs.get('jira_api_key')
|
93
|
-
|
94
|
-
|
95
|
-
except:
|
96
|
-
jira_custom_fields = {}
|
93
|
+
|
94
|
+
jira_custom_fields = kwargs.get('jira_custom_fields', {})
|
97
95
|
jira_custom_fields['team'] = kwargs.get('team_field', '')
|
98
96
|
jira_custom_fields['environment'] = kwargs.get('environment_field', '')
|
99
97
|
closed_status = kwargs.get('closed_status', '')
|
@@ -99,8 +99,6 @@ class JiraAnalyseWrapper(BaseToolApiWrapper):
|
|
99
99
|
):
|
100
100
|
"""
|
101
101
|
Extract Jira issues for the specified projects.
|
102
|
-
projects: str
|
103
|
-
one or more projects keys separated with comma
|
104
102
|
closed_issues_based_on: int
|
105
103
|
define whether issues can be thought as closed based on their status (1) or not empty resolved date (2)
|
106
104
|
resolved_after: str
|
@@ -111,8 +109,9 @@ class JiraAnalyseWrapper(BaseToolApiWrapper):
|
|
111
109
|
created after date (i.e. 2023-01-01)
|
112
110
|
add_filter: str
|
113
111
|
additional filter for Jira issues in JQL format like "customfield_10000 = 'value' AND customfield_10001 = 'value'"
|
112
|
+
project_keys: str
|
113
|
+
one or more projects keys separated with comma
|
114
114
|
"""
|
115
|
-
|
116
115
|
if not (
|
117
116
|
(
|
118
117
|
closed_issues_based_on == 1
|
@@ -123,15 +122,21 @@ class JiraAnalyseWrapper(BaseToolApiWrapper):
|
|
123
122
|
return (
|
124
123
|
"ERROR: Check input parameters closed_issues_based_on and closed_status"
|
125
124
|
)
|
125
|
+
|
126
|
+
project_keys = project_keys or self.project_keys
|
126
127
|
|
127
128
|
dispatch_custom_event(
|
128
|
-
name="
|
129
|
+
name="thinking_step",
|
129
130
|
data={
|
130
|
-
"
|
131
|
-
|
132
|
-
|
131
|
+
"message": f"I am extracting Jira issues with initial parameters:\
|
132
|
+
project keys: {project_keys}, closed status: {self.closed_status},\
|
133
|
+
defects name: {self.defects_name}, custom fields: {self.custom_fields}, \
|
134
|
+
closed status based on: {closed_issues_based_on}, resolved after: {resolved_after}, \
|
135
|
+
updated after: {updated_after}, created after: {created_after}, additional filter:{add_filter}",
|
136
|
+
"tool_name": "jira_issues_extraction_start",
|
137
|
+
"toolkit": "analyse_jira",
|
138
|
+
},
|
133
139
|
)
|
134
|
-
project_keys = project_keys or self.project_keys
|
135
140
|
|
136
141
|
jira_issues = JiraIssues(
|
137
142
|
self.jira,
|
@@ -144,12 +149,15 @@ class JiraAnalyseWrapper(BaseToolApiWrapper):
|
|
144
149
|
df_issues, df_map = jira_issues.extract_issues_from_jira_and_transform(
|
145
150
|
self.custom_fields, (resolved_after, updated_after, created_after)
|
146
151
|
)
|
152
|
+
|
147
153
|
dispatch_custom_event(
|
148
|
-
name="
|
154
|
+
name="thinking_step",
|
149
155
|
data={
|
150
|
-
"
|
151
|
-
|
152
|
-
|
156
|
+
"message": f"I am saving the extracted Jira issues to the artifact repository. \
|
157
|
+
issues count: {len(df_issues)}, mapping rows: {len(df_map)}, \
|
158
|
+
output file: {OUTPUT_MAPPING_FILE}{jira_issues.projects}.csv",
|
159
|
+
"tool_name": "get_jira_issues",
|
160
|
+
"toolkit": "analyse_jira",
|
153
161
|
},
|
154
162
|
)
|
155
163
|
self.save_dataframe(
|
@@ -157,13 +165,6 @@ class JiraAnalyseWrapper(BaseToolApiWrapper):
|
|
157
165
|
f"{OUTPUT_MAPPING_FILE}{jira_issues.projects}.csv",
|
158
166
|
csv_options={"index_label": "id"},
|
159
167
|
)
|
160
|
-
dispatch_custom_event(
|
161
|
-
name="jira_map_statuces_saved",
|
162
|
-
data={
|
163
|
-
"output_file": f"{OUTPUT_MAPPING_FILE}{jira_issues.projects}.csv",
|
164
|
-
"row_count": len(df_map),
|
165
|
-
}
|
166
|
-
)
|
167
168
|
|
168
169
|
if not df_issues.empty:
|
169
170
|
self.save_dataframe(
|
@@ -172,11 +173,14 @@ class JiraAnalyseWrapper(BaseToolApiWrapper):
|
|
172
173
|
csv_options={"index_label": "id"},
|
173
174
|
)
|
174
175
|
dispatch_custom_event(
|
175
|
-
name="
|
176
|
+
name="thinking_step",
|
176
177
|
data={
|
177
|
-
"
|
178
|
-
|
179
|
-
|
178
|
+
"message": f"Saving Jira issues to the file . \
|
179
|
+
output file: {OUTPUT_WORK_ITEMS_FILE}{jira_issues.projects}.csv,\
|
180
|
+
row count: {len(df_issues)}",
|
181
|
+
"tool_name": "get_jira_issues",
|
182
|
+
"toolkit": "analyse_jira",
|
183
|
+
},
|
180
184
|
)
|
181
185
|
|
182
186
|
return f"{jira_issues.projects} Data has been extracted successfully."
|
@@ -26,6 +26,7 @@ from ..tools.loop_output import LoopToolNode
|
|
26
26
|
from ..tools.tool import ToolNode
|
27
27
|
from ..utils.evaluate import EvaluateTemplate
|
28
28
|
from ..utils.utils import clean_string, TOOLKIT_SPLITTER
|
29
|
+
from ..tools.router import RouterNode
|
29
30
|
|
30
31
|
logger = logging.getLogger(__name__)
|
31
32
|
|
@@ -124,6 +125,58 @@ class TransitionalEdge(Runnable):
|
|
124
125
|
return self.next_step if self.next_step != 'END' else END
|
125
126
|
|
126
127
|
|
128
|
+
class StateModifierNode(Runnable):
|
129
|
+
name = "StateModifierNode"
|
130
|
+
|
131
|
+
def __init__(self, template: str, variables_to_clean: Optional[list[str]] = None,
|
132
|
+
input_variables: Optional[list[str]] = None,
|
133
|
+
output_variables: Optional[list[str]] = None):
|
134
|
+
self.template = template
|
135
|
+
self.variables_to_clean = variables_to_clean or []
|
136
|
+
self.input_variables = input_variables or ["messages"]
|
137
|
+
self.output_variables = output_variables or []
|
138
|
+
|
139
|
+
def invoke(self, state: Annotated[BaseStore, InjectedStore()], config: Optional[RunnableConfig] = None) -> dict:
|
140
|
+
logger.info(f"Modifying state with template: {self.template}")
|
141
|
+
|
142
|
+
# Collect input variables from state
|
143
|
+
input_data = {}
|
144
|
+
for var in self.input_variables:
|
145
|
+
if var in state:
|
146
|
+
input_data[var] = state.get(var)
|
147
|
+
|
148
|
+
# Render the template using Jinja
|
149
|
+
from jinja2 import Template
|
150
|
+
rendered_message = Template(self.template).render(**input_data)
|
151
|
+
result = {}
|
152
|
+
# Store the rendered message in the state or messages
|
153
|
+
if len(self.output_variables) > 0:
|
154
|
+
# Use the first output variable to store the rendered content
|
155
|
+
output_var = self.output_variables[0]
|
156
|
+
result[output_var] = rendered_message
|
157
|
+
|
158
|
+
# Clean up specified variables (make them empty, not delete)
|
159
|
+
|
160
|
+
for var in self.variables_to_clean:
|
161
|
+
if var in state:
|
162
|
+
# Empty the variable based on its type
|
163
|
+
if isinstance(state[var], list):
|
164
|
+
result[var] = []
|
165
|
+
elif isinstance(state[var], dict):
|
166
|
+
result[var] = {}
|
167
|
+
elif isinstance(state[var], str):
|
168
|
+
result[var] = ""
|
169
|
+
elif isinstance(state[var], (int, float)):
|
170
|
+
result[var] = 0
|
171
|
+
elif state[var] is None:
|
172
|
+
pass
|
173
|
+
else:
|
174
|
+
# For other types, set to None
|
175
|
+
result[var] = None
|
176
|
+
logger.info(f"State modifier result: {result}")
|
177
|
+
return result
|
178
|
+
|
179
|
+
|
127
180
|
def prepare_output_schema(lg_builder, memory, store, debug=False, interrupt_before=[], interrupt_after=[]):
|
128
181
|
# prepare output channels
|
129
182
|
output_channels = (
|
@@ -283,6 +336,32 @@ def create_graph(
|
|
283
336
|
output_variables=node.get('output', []),
|
284
337
|
input_variables=node.get('input', ['messages']),
|
285
338
|
structured_output=node.get('structured_output', False)))
|
339
|
+
elif node_type == 'router':
|
340
|
+
# Add a RouterNode as an independent node
|
341
|
+
lg_builder.add_node(node_id, RouterNode(
|
342
|
+
name=node['id'],
|
343
|
+
condition=node.get('condition', ''),
|
344
|
+
routes=node.get('routes', []),
|
345
|
+
default_output=node.get('default_output', 'END'),
|
346
|
+
input_variables=node.get('input', ['messages'])
|
347
|
+
))
|
348
|
+
# Add a single conditional edge for all routes
|
349
|
+
lg_builder.add_conditional_edges(
|
350
|
+
node_id,
|
351
|
+
ConditionalEdge(
|
352
|
+
condition="{{router_output}}", # router node returns the route key in 'router_output'
|
353
|
+
condition_inputs=["router_output"],
|
354
|
+
conditional_outputs=node.get('routes', []),
|
355
|
+
default_output=node.get('default_output', 'END')
|
356
|
+
)
|
357
|
+
)
|
358
|
+
elif node_type == 'state_modifier':
|
359
|
+
lg_builder.add_node(node_id, StateModifierNode(
|
360
|
+
template=node.get('template', ''),
|
361
|
+
variables_to_clean=node.get('variables_to_clean', []),
|
362
|
+
input_variables=node.get('input', ['messages']),
|
363
|
+
output_variables=node.get('output', [])
|
364
|
+
))
|
286
365
|
if node.get('transition'):
|
287
366
|
next_step = clean_string(node['transition'])
|
288
367
|
logger.info(f'Adding transition: {next_step}')
|
@@ -294,7 +373,7 @@ def create_graph(
|
|
294
373
|
node['decision'].get('description', ""),
|
295
374
|
decisional_inputs=node['decision'].get('decisional_inputs', ['messages']),
|
296
375
|
default_output=node['decision'].get('default_output', 'END')))
|
297
|
-
elif node.get('condition'):
|
376
|
+
elif node.get('condition') and node_type != 'router':
|
298
377
|
logger.info(f'Adding condition: {node["condition"]}')
|
299
378
|
condition_input = node['condition'].get('condition_input', ['messages'])
|
300
379
|
condition_definition = node['condition'].get('condition_definition', '')
|
alita_sdk/langchain/utils.py
CHANGED
@@ -128,7 +128,7 @@ def parse_type(type_str):
|
|
128
128
|
|
129
129
|
|
130
130
|
def create_state(data: Optional[dict] = None):
|
131
|
-
state_dict = {'input': str,}
|
131
|
+
state_dict = {'input': str, 'router_output': str} # Always include router_output
|
132
132
|
if not data:
|
133
133
|
data = {'messages': 'list[str]'}
|
134
134
|
for key, value in data.items():
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import logging
|
2
|
+
from typing import Any, Optional, Union, List
|
3
|
+
from langchain_core.runnables import RunnableConfig
|
4
|
+
from langchain_core.tools import BaseTool
|
5
|
+
from ..utils.evaluate import EvaluateTemplate
|
6
|
+
from ..utils.utils import clean_string
|
7
|
+
|
8
|
+
logger = logging.getLogger(__name__)
|
9
|
+
|
10
|
+
class RouterNode(BaseTool):
|
11
|
+
name: str = 'RouterNode'
|
12
|
+
description: str = 'A router node that evaluates a condition and routes accordingly.'
|
13
|
+
condition: str = ''
|
14
|
+
routes: List[str] = [] # List of possible output node keys
|
15
|
+
default_output: str = 'END'
|
16
|
+
input_variables: Optional[list[str]] = None
|
17
|
+
|
18
|
+
def invoke(self, state: Union[str, dict], config: Optional[RunnableConfig] = None, **kwargs: Any) -> dict:
|
19
|
+
input_data = {}
|
20
|
+
for field in self.input_variables or []:
|
21
|
+
input_data[field] = state.get(field, "")
|
22
|
+
template = EvaluateTemplate(self.condition, input_data)
|
23
|
+
result = template.evaluate()
|
24
|
+
logger.info(f"RouterNode evaluated condition '{self.condition}' with input {input_data} => {result}")
|
25
|
+
result = clean_string(str(result))
|
26
|
+
if result in self.routes:
|
27
|
+
# If the result is one of the routes, return it
|
28
|
+
return {"router_output": result}
|
29
|
+
elif result == self.default_output:
|
30
|
+
# If the result is the default output, return it
|
31
|
+
return {"router_output": clean_string(self.default_output)}
|
32
|
+
return {"router_output": 'END'}
|
33
|
+
|
34
|
+
def _run(self, *args, **kwargs):
|
35
|
+
return self.invoke(**kwargs)
|
alita_sdk/utils/AlitaCallback.py
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import logging
|
2
2
|
import json
|
3
3
|
import traceback
|
4
|
+
from datetime import datetime, timezone
|
4
5
|
from uuid import UUID, uuid4
|
5
6
|
from typing import Any, Dict, List, Optional
|
6
7
|
from collections import defaultdict
|
@@ -51,6 +52,35 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
|
|
51
52
|
# Tool
|
52
53
|
#
|
53
54
|
|
55
|
+
def on_custom_event(
|
56
|
+
self,
|
57
|
+
name: str,
|
58
|
+
data: Any,
|
59
|
+
*,
|
60
|
+
run_id: UUID,
|
61
|
+
tags: Optional[List[str]] = None,
|
62
|
+
metadata: Optional[Dict[str, Any]] = None,
|
63
|
+
**kwargs: Any,
|
64
|
+
) -> None:
|
65
|
+
"""Callback containing a group of custom events"""
|
66
|
+
|
67
|
+
payload = {
|
68
|
+
"name": name,
|
69
|
+
"run_id": str(run_id),
|
70
|
+
"tool_run_id": str(run_id), # compatibility
|
71
|
+
"metadata": metadata,
|
72
|
+
"datetime": str(datetime.now(tz=timezone.utc)),
|
73
|
+
**data,
|
74
|
+
}
|
75
|
+
payload = json.loads(
|
76
|
+
json.dumps(payload, ensure_ascii=False, default=lambda o: str(o))
|
77
|
+
)
|
78
|
+
|
79
|
+
self.callback_state[str(run_id)] = self.st.status(
|
80
|
+
f"Running {payload.get("tool_name")}...", expanded=True
|
81
|
+
)
|
82
|
+
self.callback_state[str(run_id)].write(f"Tool inputs: {payload}")
|
83
|
+
|
54
84
|
def on_tool_start(self, *args, run_id: UUID, **kwargs):
|
55
85
|
""" Callback """
|
56
86
|
if self.debug:
|
@@ -125,7 +155,7 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
|
|
125
155
|
|
126
156
|
self.current_model_name = metadata.get('ls_model_name', self.current_model_name)
|
127
157
|
llm_run_id = str(run_id)
|
128
|
-
|
158
|
+
|
129
159
|
self.callback_state[llm_run_id] = self.st.status(f"Running LLM ...", expanded=True)
|
130
160
|
self.callback_state[llm_run_id].write(f"LLM inputs: {messages}")
|
131
161
|
|
@@ -176,4 +206,4 @@ class AlitaStreamlitCallback(BaseCallbackHandler):
|
|
176
206
|
log.debug("on_llm_end(%s, %s)", response, kwargs)
|
177
207
|
llm_run_id = str(run_id)
|
178
208
|
self.callback_state[llm_run_id].update(label=f"Completed LLM call", state="complete", expanded=False)
|
179
|
-
self.callback_state.pop(llm_run_id, None)
|
209
|
+
self.callback_state.pop(llm_run_id, None)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: alita_sdk
|
3
|
-
Version: 0.3.
|
3
|
+
Version: 0.3.117
|
4
4
|
Summary: SDK for building langchain agents using resouces 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 <lifedjik@gmail.com>
|
6
6
|
Project-URL: Homepage, https://projectalita.ai
|
@@ -10,8 +10,8 @@ alita_sdk/clients/prompt.py,sha256=li1RG9eBwgNK_Qf0qUaZ8QNTmsncFrAL2pv3kbxZRZg,1
|
|
10
10
|
alita_sdk/community/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
11
11
|
alita_sdk/community/utils.py,sha256=lvuCJaNqVPHOORJV6kIPcXJcdprVW_TJvERtYAEgpjM,249
|
12
12
|
alita_sdk/community/analysis/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
13
|
-
alita_sdk/community/analysis/jira_analyse/__init__.py,sha256=
|
14
|
-
alita_sdk/community/analysis/jira_analyse/api_wrapper.py,sha256=
|
13
|
+
alita_sdk/community/analysis/jira_analyse/__init__.py,sha256=Rm-HKEi_HIxrgHdq9mZ-XzxMKLXm8-81eJwJT2lar-c,5945
|
14
|
+
alita_sdk/community/analysis/jira_analyse/api_wrapper.py,sha256=FPYAOh2SV5ggWg0ywDdkyt6udyR3juQvZM7lOIwvcKU,9327
|
15
15
|
alita_sdk/community/browseruse/__init__.py,sha256=uAxPZEX7ihpt8HtcGDFrzTNv9WcklT1wG1ItTwUO8y4,3601
|
16
16
|
alita_sdk/community/browseruse/api_wrapper.py,sha256=Y05NKWfTROPmBxe8ZFIELSGBX5v3RTNP30OTO2Tj8uI,10838
|
17
17
|
alita_sdk/langchain/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
@@ -19,10 +19,10 @@ alita_sdk/langchain/assistant.py,sha256=V0MpZG9IQRlKMr1SfAabVbUsIp-gNPO9A1SWxuFi
|
|
19
19
|
alita_sdk/langchain/chat_message_template.py,sha256=kPz8W2BG6IMyITFDA5oeb5BxVRkHEVZhuiGl4MBZKdc,2176
|
20
20
|
alita_sdk/langchain/constants.py,sha256=eHVJ_beJNTf1WJo4yq7KMK64fxsRvs3lKc34QCXSbpk,3319
|
21
21
|
alita_sdk/langchain/indexer.py,sha256=0ENHy5EOhThnAiYFc7QAsaTNp9rr8hDV_hTK8ahbatk,37592
|
22
|
-
alita_sdk/langchain/langraph_agent.py,sha256=
|
22
|
+
alita_sdk/langchain/langraph_agent.py,sha256=vxsbjOE0UWZIuyXNGEMR1QJ8t5yHS7Kzjt8a8nLb-jw,20626
|
23
23
|
alita_sdk/langchain/mixedAgentParser.py,sha256=M256lvtsL3YtYflBCEp-rWKrKtcY1dJIyRGVv7KW9ME,2611
|
24
24
|
alita_sdk/langchain/mixedAgentRenderes.py,sha256=asBtKqm88QhZRILditjYICwFVKF5KfO38hu2O-WrSWE,5964
|
25
|
-
alita_sdk/langchain/utils.py,sha256=
|
25
|
+
alita_sdk/langchain/utils.py,sha256=Npferkn10dvdksnKzLJLBI5bNGQyVWTBwqp3vQtUqmY,6631
|
26
26
|
alita_sdk/langchain/agents/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
27
27
|
alita_sdk/langchain/agents/xml_chat.py,sha256=Mx7PK5T97_GrFCwHHZ3JZP42S7MwtUzV0W-_8j6Amt8,6212
|
28
28
|
alita_sdk/langchain/document_loaders/AlitaBDDScenariosLoader.py,sha256=4kFU1ijrM1Jw7cywQv8mUiBHlE6w-uqfzSZP4hUV5P4,3771
|
@@ -82,17 +82,18 @@ alita_sdk/tools/loop.py,sha256=uds0WhZvwMxDVFI6MZHrcmMle637cQfBNg682iLxoJA,8335
|
|
82
82
|
alita_sdk/tools/loop_output.py,sha256=NoGIGYc42wY3NNcWRijYzRnUVXcCn5cRVd8QmuIpoHU,8068
|
83
83
|
alita_sdk/tools/pgvector_search.py,sha256=NN2BGAnq4SsDHIhUcFZ8d_dbEOM8QwB0UwpsWCYruXU,11692
|
84
84
|
alita_sdk/tools/prompt.py,sha256=nJafb_e5aOM1Rr3qGFCR-SKziU9uCsiP2okIMs9PppM,741
|
85
|
+
alita_sdk/tools/router.py,sha256=wCvZjVkdXK9dMMeEerrgKf5M790RudH68pDortnHSz0,1517
|
85
86
|
alita_sdk/tools/tool.py,sha256=jFRq8BeC55NwpgdpsqGk_Y3tZL4YKN0rE7sVS5OE3yg,5092
|
86
87
|
alita_sdk/tools/vectorstore.py,sha256=F-DoHxPa4UVsKB-FEd-wWa59QGQifKMwcSNcZ5WZOKc,23496
|
87
|
-
alita_sdk/utils/AlitaCallback.py,sha256=
|
88
|
+
alita_sdk/utils/AlitaCallback.py,sha256=cvpDhR4QLVCNQci6CO6TEUrUVDZU9_CRSwzcHGm3SGw,7356
|
88
89
|
alita_sdk/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
89
90
|
alita_sdk/utils/evaluate.py,sha256=iM1P8gzBLHTuSCe85_Ng_h30m52hFuGuhNXJ7kB1tgI,1872
|
90
91
|
alita_sdk/utils/streamlit.py,sha256=zp8owZwHI3HZplhcExJf6R3-APtWx-z6s5jznT2hY_k,29124
|
91
92
|
alita_sdk/utils/utils.py,sha256=dM8whOJAuFJFe19qJ69-FLzrUp6d2G-G6L7d4ss2XqM,346
|
92
|
-
alita_sdk-0.3.
|
93
|
+
alita_sdk-0.3.117.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
93
94
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
94
95
|
tests/test_jira_analysis.py,sha256=I0cErH5R_dHVyutpXrM1QEo7jfBuKWTmDQvJBPjx18I,3281
|
95
|
-
alita_sdk-0.3.
|
96
|
-
alita_sdk-0.3.
|
97
|
-
alita_sdk-0.3.
|
98
|
-
alita_sdk-0.3.
|
96
|
+
alita_sdk-0.3.117.dist-info/METADATA,sha256=UKs2mCU1AvQTt5jMaeRngvrGk8z6WwY4DX6aNBmaEzo,7075
|
97
|
+
alita_sdk-0.3.117.dist-info/WHEEL,sha256=zaaOINJESkSfm_4HQVc5ssNzHCPXhJm0kEUakpsEHaU,91
|
98
|
+
alita_sdk-0.3.117.dist-info/top_level.txt,sha256=SWRhxB7Et3cOy3RkE5hR7OIRnHoo3K8EXzoiNlkfOmc,25
|
99
|
+
alita_sdk-0.3.117.dist-info/RECORD,,
|
File without changes
|
File without changes
|