Skip to content

Commit bac46ee

Browse files
committed
Version 1.4.76
1 parent 1f6017d commit bac46ee

337 files changed

Lines changed: 1585 additions & 121 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

abacusai/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,10 @@
286286
from .web_page_response import WebPageResponse
287287
from .web_search_response import WebSearchResponse
288288
from .web_search_result import WebSearchResult
289+
from .web_service_trigger_run import WebServiceTriggerRun
289290
from .webhook import Webhook
290291
from .workflow_graph_node_details import WorkflowGraphNodeDetails
291292
from .workflow_node_template import WorkflowNodeTemplate
292293

293294

294-
__version__ = "1.4.75"
295+
__version__ = "1.4.76"

abacusai/api_class/ai_agents.py

Lines changed: 29 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -223,18 +223,25 @@ def from_tool_variable_mappings(cls, tool_variable_mappings: dict):
223223
Args:
224224
tool_variable_mappings (List[dict]): The tool variable mappings for the node.
225225
"""
226-
json_schema = {'type': 'object', 'properties': {}}
226+
json_schema = {'type': 'object', 'properties': {}, 'required': []}
227+
ui_schema = {}
227228
for mapping in tool_variable_mappings:
228229
json_schema['properties'][mapping['name']] = {'title': mapping['name'], 'type': enums.PythonFunctionArgumentType.to_json_type(mapping['variable_type'])}
229230
if mapping.get('description'):
230231
json_schema['properties'][mapping['name']]['description'] = mapping['description']
231232
if mapping['variable_type'] == enums.PythonFunctionArgumentType.ATTACHMENT:
232233
json_schema['properties'][mapping['name']]['format'] = 'data-url'
234+
ui_schema[mapping['name']] = {'ui:widget': 'file'}
233235
if mapping['variable_type'] == enums.PythonFunctionArgumentType.LIST:
234-
json_schema['properties'][mapping['name']]['items'] = {'type': enums.PythonFunctionArgumentType.to_json_type(mapping['item_type'])}
235236
if mapping['item_type'] == enums.PythonFunctionArgumentType.ATTACHMENT:
236-
json_schema['properties'][mapping['name']]['items']['format'] = 'data-url'
237-
return cls(json_schema=json_schema)
237+
json_schema['properties'][mapping['name']]['type'] = 'string'
238+
json_schema['properties'][mapping['name']]['format'] = 'data-url'
239+
ui_schema[mapping['name']] = {'ui:widget': 'file', 'ui:options': {'multiple': True}}
240+
else:
241+
json_schema['properties'][mapping['name']]['items'] = {'type': enums.PythonFunctionArgumentType.to_json_type(mapping['item_type'])}
242+
if mapping['is_required']:
243+
json_schema['required'].append(mapping['name'])
244+
return cls(json_schema=json_schema, ui_schema=ui_schema)
238245

239246

240247
@validate_constructor_arg_types('output_mapping')
@@ -756,29 +763,18 @@ def __init__(self, name: str, chatbot_deployment_id: str = None, chatbot_paramet
756763

757764
# Prepare input and output mappings
758765
input_mappings = [
759-
WorkflowNodeInputMapping(name='user_input', variable_type=enums.WorkflowNodeInputType.USER_INPUT, is_required=True),
760-
WorkflowNodeInputMapping(name='attachment_input', variable_type=enums.WorkflowNodeInputType.USER_INPUT, is_required=False, description='Optional file attachment to include with the message')
766+
WorkflowNodeInputMapping(name='user_input', variable_type=enums.WorkflowNodeInputType.USER_INPUT, is_required=True)
761767
]
762768
output_mappings = [WorkflowNodeOutputMapping(name='chat_output', variable_type=enums.WorkflowNodeOutputType.DICT, description='The output of the chatbot')]
763769

764770
# Determine function_name and create minimal source_code for parent validation
765771
# Always use get_function_name() which includes uid to ensure uniqueness
766772
function_name = self.get_function_name()
767-
minimal_source_code = f'def {function_name}(user_input, attachment_input=None):\n pass'
773+
minimal_source_code = f'def {function_name}(user_input):\n pass'
768774

769-
# Customize input schema to mark attachment_input as a file type
775+
# Generate input schema from input mappings if not provided
770776
if input_schema is None:
771-
base_schema = WorkflowNodeInputSchema.from_input_mappings(input_mappings)
772-
# Override attachment_input to be a file format in json_schema
773-
if base_schema.json_schema.get('properties', {}).get('attachment_input'):
774-
base_schema.json_schema['properties']['attachment_input']['type'] = 'string'
775-
base_schema.json_schema['properties']['attachment_input']['format'] = 'data-url'
776-
base_schema.json_schema['properties']['attachment_input']['description'] = 'Optional file attachment to include with the message'
777-
# Set ui_schema to use file widget for attachment_input
778-
if not base_schema.ui_schema:
779-
base_schema.ui_schema = {}
780-
base_schema.ui_schema['attachment_input'] = {'ui:widget': 'file'}
781-
input_schema = base_schema
777+
input_schema = WorkflowNodeInputSchema.from_input_mappings(input_mappings)
782778

783779
# Initialize parent class with minimal source code to satisfy validation
784780
super().__init__(name=name, function_name=function_name, source_code=minimal_source_code, input_mappings=input_mappings, output_mappings=output_mappings, input_schema=input_schema, output_schema=output_schema or WorkflowNodeOutputSchema.from_fields_list(['chat_output']))
@@ -882,8 +878,8 @@ def _mark_file_inputs_in_schema(input_schema: WorkflowNodeInputSchema) -> None:
882878
prop_schema['format'] = 'data-url'
883879
input_schema.ui_schema[prop_name] = {'ui:widget': 'file'}
884880

885-
def __init__(self, name: str, input_mappings: Union[Dict[str, WorkflowNodeInputMapping], List[WorkflowNodeInputMapping]] = None, output_mappings: Union[List[str], Dict[str, str], List[WorkflowNodeOutputMapping]] = None, input_schema: WorkflowNodeInputSchema = None, output_schema: WorkflowNodeOutputSchema = None, description: str = None):
886-
self.uid = str(uuid.uuid4())[:6]
881+
def __init__(self, name: str, input_mappings: Union[Dict[str, WorkflowNodeInputMapping], List[WorkflowNodeInputMapping]] = None, output_mappings: Union[List[str], Dict[str, str], List[WorkflowNodeOutputMapping]] = None, input_schema: WorkflowNodeInputSchema = None, output_schema: WorkflowNodeOutputSchema = None, description: str = None, function_name: str = None, source_code: str = None, uid: str = None):
882+
self.uid = uid or str(uuid.uuid4())[:6]
887883

888884
if input_mappings is None:
889885
input_mappings = [
@@ -909,7 +905,7 @@ def __init__(self, name: str, input_mappings: Union[Dict[str, WorkflowNodeInputM
909905
)
910906
]
911907

912-
function_name = self.get_function_name()
908+
function_name = function_name or self.get_function_name()
913909

914910
if input_schema is None:
915911
input_schema = WorkflowNodeInputSchema.from_input_mappings(input_mappings)
@@ -937,15 +933,15 @@ def __init__(self, name: str, input_mappings: Union[Dict[str, WorkflowNodeInputM
937933
super().__init__(
938934
name=name,
939935
function_name=function_name,
940-
source_code=None,
936+
source_code=source_code,
941937
input_mappings=input_mappings,
942938
output_mappings=output_mappings,
943939
input_schema=input_schema,
944940
output_schema=output_schema,
945941
description=description
946942
)
947943
self.node_type = 'input_node'
948-
self.source_code = None
944+
self.source_code = source_code
949945
self.template_metadata = None
950946
self.trigger_config = None
951947

@@ -972,34 +968,29 @@ def to_dict(self):
972968

973969
@classmethod
974970
def from_dict(cls, node: dict):
971+
uid = node.get('uid')
972+
function_name = node.get('function_name')
973+
source_code = node.get('source_code')
974+
975975
instance = cls(
976976
name=node['name'],
977+
uid=uid,
978+
function_name=function_name,
979+
source_code=source_code,
977980
input_mappings=[WorkflowNodeInputMapping.from_dict(mapping) for mapping in node.get('input_mappings', [])],
978981
output_mappings=[WorkflowNodeOutputMapping.from_dict(mapping) for mapping in node.get('output_mappings', [])],
979982
input_schema=WorkflowNodeInputSchema.from_dict(node.get('input_schema', {})),
980983
output_schema=WorkflowNodeOutputSchema.from_dict(node.get('output_schema', {})),
981984
description=node.get('description'),
982985
)
983-
# Preserve uid from dict if it exists (for round-trip serialization of existing workflows)
984-
if 'uid' in node and node.get('uid'):
985-
instance.uid = node['uid']
986-
# Regenerate function_name with preserved uid
987-
instance.function_name = f'input_node_{instance.uid}'
988-
# Regenerate source_code so it matches the preserved uid/function_name
989-
instance.source_code = instance.get_source_code()
990986
return instance
991987

992988
def get_function_name(self):
993989
return f'input_node_{self.uid}'
994990

995991
def get_source_code(self):
996-
"""Return None for input node source code.
997-
998-
Input nodes are executed directly without source code validation,
999-
similar to LLM agent nodes. The minimal source code is only used during
1000-
initialization to satisfy parent class validation.
1001-
"""
1002-
return None
992+
"""Return the stored source code, if any."""
993+
return self.source_code
1003994

1004995
def get_input_schema(self):
1005996
return self.input_schema

abacusai/api_class/enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,7 @@ class LLMName(ApiEnum):
566566
GEMINI_2_5_PRO = 'GEMINI_2_5_PRO'
567567
GEMINI_3_PRO = 'GEMINI_3_PRO'
568568
GEMINI_2_5_FLASH = 'GEMINI_2_5_FLASH'
569+
GEMINI_3_FLASH = 'GEMINI_3_FLASH'
569570
XAI_GROK = 'XAI_GROK'
570571
XAI_GROK_3 = 'XAI_GROK_3'
571572
XAI_GROK_3_MINI = 'XAI_GROK_3_MINI'

abacusai/chatllm_task.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class ChatllmTask(AbstractApiClass):
1212
taskType (str): The type of task ('chatllm' or 'daemon').
1313
name (str): The name of the chatllm task.
1414
instructions (str): The instructions of the chatllm task.
15+
description (str): The description of the chatllm task.
1516
lifecycle (str): The lifecycle of the chatllm task.
1617
scheduleInfo (dict): The schedule info of the chatllm task.
1718
externalApplicationId (str): The external application id associated with the chatllm task.
@@ -23,15 +24,18 @@ class ChatllmTask(AbstractApiClass):
2324
computePointsUsed (int): The compute points used for the chatllm task.
2425
displayMarkdown (str): The display markdown for the chatllm task.
2526
requiresNewConversation (bool): Whether a new conversation is required for the chatllm task.
27+
executionMode (str): The execution mode of the chatllm task.
28+
taskDefinition (dict): The task definition (for web_service_trigger tasks).
2629
"""
2730

28-
def __init__(self, client, chatllmTaskId=None, daemonTaskId=None, taskType=None, name=None, instructions=None, lifecycle=None, scheduleInfo=None, externalApplicationId=None, deploymentConversationId=None, sourceDeploymentConversationId=None, enableEmailAlerts=None, email=None, numUnreadTaskInstances=None, computePointsUsed=None, displayMarkdown=None, requiresNewConversation=None):
31+
def __init__(self, client, chatllmTaskId=None, daemonTaskId=None, taskType=None, name=None, instructions=None, description=None, lifecycle=None, scheduleInfo=None, externalApplicationId=None, deploymentConversationId=None, sourceDeploymentConversationId=None, enableEmailAlerts=None, email=None, numUnreadTaskInstances=None, computePointsUsed=None, displayMarkdown=None, requiresNewConversation=None, executionMode=None, taskDefinition=None):
2932
super().__init__(client, chatllmTaskId)
3033
self.chatllm_task_id = chatllmTaskId
3134
self.daemon_task_id = daemonTaskId
3235
self.task_type = taskType
3336
self.name = name
3437
self.instructions = instructions
38+
self.description = description
3539
self.lifecycle = lifecycle
3640
self.schedule_info = scheduleInfo
3741
self.external_application_id = externalApplicationId
@@ -43,11 +47,13 @@ def __init__(self, client, chatllmTaskId=None, daemonTaskId=None, taskType=None,
4347
self.compute_points_used = computePointsUsed
4448
self.display_markdown = displayMarkdown
4549
self.requires_new_conversation = requiresNewConversation
50+
self.execution_mode = executionMode
51+
self.task_definition = taskDefinition
4652
self.deprecated_keys = {}
4753

4854
def __repr__(self):
49-
repr_dict = {f'chatllm_task_id': repr(self.chatllm_task_id), f'daemon_task_id': repr(self.daemon_task_id), f'task_type': repr(self.task_type), f'name': repr(self.name), f'instructions': repr(self.instructions), f'lifecycle': repr(self.lifecycle), f'schedule_info': repr(self.schedule_info), f'external_application_id': repr(self.external_application_id), f'deployment_conversation_id': repr(
50-
self.deployment_conversation_id), f'source_deployment_conversation_id': repr(self.source_deployment_conversation_id), f'enable_email_alerts': repr(self.enable_email_alerts), f'email': repr(self.email), f'num_unread_task_instances': repr(self.num_unread_task_instances), f'compute_points_used': repr(self.compute_points_used), f'display_markdown': repr(self.display_markdown), f'requires_new_conversation': repr(self.requires_new_conversation)}
55+
repr_dict = {f'chatllm_task_id': repr(self.chatllm_task_id), f'daemon_task_id': repr(self.daemon_task_id), f'task_type': repr(self.task_type), f'name': repr(self.name), f'instructions': repr(self.instructions), f'description': repr(self.description), f'lifecycle': repr(self.lifecycle), f'schedule_info': repr(self.schedule_info), f'external_application_id': repr(self.external_application_id), f'deployment_conversation_id': repr(self.deployment_conversation_id), f'source_deployment_conversation_id': repr(
56+
self.source_deployment_conversation_id), f'enable_email_alerts': repr(self.enable_email_alerts), f'email': repr(self.email), f'num_unread_task_instances': repr(self.num_unread_task_instances), f'compute_points_used': repr(self.compute_points_used), f'display_markdown': repr(self.display_markdown), f'requires_new_conversation': repr(self.requires_new_conversation), f'execution_mode': repr(self.execution_mode), f'task_definition': repr(self.task_definition)}
5157
class_name = "ChatllmTask"
5258
repr_str = ',\n '.join([f'{key}={value}' for key, value in repr_dict.items(
5359
) if getattr(self, key, None) is not None and key not in self.deprecated_keys])
@@ -60,6 +66,6 @@ def to_dict(self):
6066
Returns:
6167
dict: The dict value representation of the class parameters
6268
"""
63-
resp = {'chatllm_task_id': self.chatllm_task_id, 'daemon_task_id': self.daemon_task_id, 'task_type': self.task_type, 'name': self.name, 'instructions': self.instructions, 'lifecycle': self.lifecycle, 'schedule_info': self.schedule_info, 'external_application_id': self.external_application_id, 'deployment_conversation_id': self.deployment_conversation_id,
64-
'source_deployment_conversation_id': self.source_deployment_conversation_id, 'enable_email_alerts': self.enable_email_alerts, 'email': self.email, 'num_unread_task_instances': self.num_unread_task_instances, 'compute_points_used': self.compute_points_used, 'display_markdown': self.display_markdown, 'requires_new_conversation': self.requires_new_conversation}
69+
resp = {'chatllm_task_id': self.chatllm_task_id, 'daemon_task_id': self.daemon_task_id, 'task_type': self.task_type, 'name': self.name, 'instructions': self.instructions, 'description': self.description, 'lifecycle': self.lifecycle, 'schedule_info': self.schedule_info, 'external_application_id': self.external_application_id, 'deployment_conversation_id': self.deployment_conversation_id,
70+
'source_deployment_conversation_id': self.source_deployment_conversation_id, 'enable_email_alerts': self.enable_email_alerts, 'email': self.email, 'num_unread_task_instances': self.num_unread_task_instances, 'compute_points_used': self.compute_points_used, 'display_markdown': self.display_markdown, 'requires_new_conversation': self.requires_new_conversation, 'execution_mode': self.execution_mode, 'task_definition': self.task_definition}
6571
return {key: value for key, value in resp.items() if value is not None and key not in self.deprecated_keys}

abacusai/client.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ class BaseApiClient:
667667
client_options (ClientOptions): Optional API client configurations
668668
skip_version_check (bool): If true, will skip checking the server's current API version on initializing the client
669669
"""
670-
client_version = '1.4.75'
670+
client_version = '1.4.76'
671671

672672
def __init__(self, api_key: str = None, server: str = None, client_options: ClientOptions = None, skip_version_check: bool = False, include_tb: bool = False):
673673
self.api_key = api_key

0 commit comments

Comments
 (0)