66from ..._utils import Endpoint , RequestSpec , header_folder , resource_override
77from ..._utils .constants import ENV_JOB_KEY , HEADER_JOB_KEY
88from ...tracing import traced
9+ from ..attachments import Attachment
910from ..common import BaseService , FolderContext , UiPathApiConfig , UiPathExecutionContext
1011from ._attachments_service import AttachmentsService
1112from .job import Job
@@ -19,6 +20,8 @@ class ProcessesService(FolderContext, BaseService):
1920 specific business tasks.
2021 """
2122
23+ _INPUT_ARGUMENTS_SIZE_LIMIT = 10000
24+
2225 def __init__ (
2326 self ,
2427 config : UiPathApiConfig ,
@@ -37,6 +40,7 @@ def invoke(
3740 * ,
3841 folder_key : Optional [str ] = None ,
3942 folder_path : Optional [str ] = None ,
43+ attachments : Optional [list [Attachment ]] = None ,
4044 ) -> Job :
4145 """Start execution of a process by its name.
4246
@@ -45,6 +49,7 @@ def invoke(
4549 Args:
4650 name (str): The name of the process to execute.
4751 input_arguments (Optional[Dict[str, Any]]): The input arguments to pass to the process.
52+ attachments (Optional[list]): List of Attachment objects to pass to the process.
4853 folder_key (Optional[str]): The key of the folder to execute the process in. Override the default one set in the SDK config.
4954 folder_path (Optional[str]): The path of the folder to execute the process in. Override the default one set in the SDK config.
5055
@@ -72,9 +77,11 @@ def invoke(
7277 """
7378 input_data = self ._handle_input_arguments (
7479 input_arguments = input_arguments ,
80+ attachments = attachments ,
7581 folder_key = folder_key ,
7682 folder_path = folder_path ,
7783 )
84+
7885 spec = self ._invoke_spec (
7986 name ,
8087 input_data = input_data ,
@@ -101,6 +108,7 @@ async def invoke_async(
101108 * ,
102109 folder_key : Optional [str ] = None ,
103110 folder_path : Optional [str ] = None ,
111+ attachments : Optional [list [Attachment ]] = None ,
104112 ) -> Job :
105113 """Asynchronously start execution of a process by its name.
106114
@@ -109,6 +117,7 @@ async def invoke_async(
109117 Args:
110118 name (str): The name of the process to execute.
111119 input_arguments (Optional[Dict[str, Any]]): The input arguments to pass to the process.
120+ attachments (Optional[list]): List of Attachment objects to pass to the process.
112121 folder_key (Optional[str]): The key of the folder to execute the process in. Override the default one set in the SDK config.
113122 folder_path (Optional[str]): The path of the folder to execute the process in. Override the default one set in the SDK config.
114123
@@ -132,6 +141,7 @@ async def main():
132141 """
133142 input_data = await self ._handle_input_arguments_async (
134143 input_arguments = input_arguments ,
144+ attachments = attachments ,
135145 folder_key = folder_key ,
136146 folder_path = folder_path ,
137147 )
@@ -157,71 +167,104 @@ async def main():
157167 def custom_headers (self ) -> Dict [str , str ]:
158168 return self .folder_headers
159169
170+ @staticmethod
171+ def _prepare_link_attachments (
172+ attachments : Optional [list [Attachment ]],
173+ ) -> Optional [list [Dict [str , str ]]]:
174+ """Format attachments for process invocation payload."""
175+ if not attachments :
176+ return None
177+
178+ link_attachments = [
179+ {"attachmentId" : str (att .id )} for att in attachments if att .id is not None
180+ ]
181+ return link_attachments if link_attachments else None
182+
160183 def _handle_input_arguments (
161184 self ,
162185 input_arguments : Optional [Dict [str , Any ]] = None ,
186+ attachments : Optional [list [Attachment ]] = None ,
163187 * ,
164188 folder_key : Optional [str ] = None ,
165189 folder_path : Optional [str ] = None ,
166- ) -> Dict [str , str ]:
167- """Handle input arguments, storing as attachment if they exceed size limit.
190+ ) -> Dict [str , Any ]:
191+ """Handle input arguments and attachments , storing as attachment if they exceed size limit.
168192
169193 Args:
170194 input_arguments: The input arguments to process
195+ attachments: List of Attachment objects to pass to the process
171196 folder_key: The folder key for attachment storage
172197 folder_path: The folder path for attachment storage
173198
174199 Returns:
175- Dict containing either "InputArguments" or "InputFile" key
200+ Dict containing either "InputArguments" or "InputFile" key, and optionally "Attachments"
176201 """
202+ result : Dict [str , Any ] = {}
203+
204+ # handle input arguments
177205 if not input_arguments :
178- return {"InputArguments" : json .dumps ({})}
179-
180- # If payload exceeds limit, store as attachment
181- payload_json = json .dumps (input_arguments )
182- if len (payload_json ) > 10000 : # 10k char limit
183- attachment_id = self ._attachments_service .upload (
184- name = f"{ uuid .uuid4 ()} .json" ,
185- content = payload_json ,
186- folder_key = folder_key ,
187- folder_path = folder_path ,
188- )
189- return {"InputFile" : str (attachment_id )}
206+ result ["InputArguments" ] = json .dumps ({})
190207 else :
191- return {"InputArguments" : payload_json }
208+ # If payload exceeds limit, store as attachment
209+ payload_json = json .dumps (input_arguments )
210+ if len (payload_json ) > self ._INPUT_ARGUMENTS_SIZE_LIMIT :
211+ attachment_id = self ._attachments_service .upload (
212+ name = f"{ uuid .uuid4 ()} .json" ,
213+ content = payload_json ,
214+ folder_key = folder_key ,
215+ folder_path = folder_path ,
216+ )
217+ result ["InputFile" ] = str (attachment_id )
218+ else :
219+ result ["InputArguments" ] = payload_json
220+
221+ link_attachments = self ._prepare_link_attachments (attachments )
222+ if link_attachments :
223+ result ["Attachments" ] = link_attachments
224+
225+ return result
192226
193227 async def _handle_input_arguments_async (
194228 self ,
195229 input_arguments : Optional [Dict [str , Any ]] = None ,
230+ attachments : Optional [list [Attachment ]] = None ,
196231 * ,
197232 folder_key : Optional [str ] = None ,
198233 folder_path : Optional [str ] = None ,
199- ) -> Dict [str , str ]:
200- """Handle input arguments, storing as attachment if they exceed size limit.
234+ ) -> Dict [str , Any ]:
235+ """Handle input arguments and attachments , storing as attachment if they exceed size limit.
201236
202237 Args:
203238 input_arguments: The input arguments to process
239+ attachments: List of Attachment objects to pass to the process
204240 folder_key: The folder key for attachment storage
205241 folder_path: The folder path for attachment storage
206242
207243 Returns:
208- Dict containing either "InputArguments" or "InputFile" key
244+ Dict containing either "InputArguments" or "InputFile" key, and optionally "Attachments"
209245 """
246+ result : Dict [str , Any ] = {}
247+
210248 if not input_arguments :
211- return {"InputArguments" : json .dumps ({})}
212-
213- # If payload exceeds limit, store as attachment
214- payload_json = json .dumps (input_arguments )
215- if len (payload_json ) > 10000 : # 10k char limit
216- attachment_id = await self ._attachments_service .upload_async (
217- name = f"{ uuid .uuid4 ()} .json" ,
218- content = payload_json ,
219- folder_key = folder_key ,
220- folder_path = folder_path ,
221- )
222- return {"InputFile" : str (attachment_id )}
249+ result ["InputArguments" ] = json .dumps ({})
223250 else :
224- return {"InputArguments" : payload_json }
251+ payload_json = json .dumps (input_arguments )
252+ if len (payload_json ) > self ._INPUT_ARGUMENTS_SIZE_LIMIT :
253+ attachment_id = await self ._attachments_service .upload_async (
254+ name = f"{ uuid .uuid4 ()} .json" ,
255+ content = payload_json ,
256+ folder_key = folder_key ,
257+ folder_path = folder_path ,
258+ )
259+ result ["InputFile" ] = str (attachment_id )
260+ else :
261+ result ["InputArguments" ] = payload_json
262+
263+ formatted_attachments = self ._prepare_link_attachments (attachments )
264+ if formatted_attachments :
265+ result ["Attachments" ] = formatted_attachments
266+
267+ return result
225268
226269 def _invoke_spec (
227270 self ,
0 commit comments