uipath-langchain 0.0.133__py3-none-any.whl → 0.1.28__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.
Files changed (83) hide show
  1. uipath_langchain/_cli/cli_init.py +130 -191
  2. uipath_langchain/_cli/cli_new.py +2 -3
  3. uipath_langchain/_resources/AGENTS.md +21 -0
  4. uipath_langchain/_resources/REQUIRED_STRUCTURE.md +92 -0
  5. uipath_langchain/_tracing/__init__.py +3 -2
  6. uipath_langchain/_tracing/_instrument_traceable.py +11 -12
  7. uipath_langchain/_utils/_request_mixin.py +327 -51
  8. uipath_langchain/_utils/_settings.py +2 -2
  9. uipath_langchain/agent/exceptions/__init__.py +6 -0
  10. uipath_langchain/agent/exceptions/exceptions.py +11 -0
  11. uipath_langchain/agent/guardrails/__init__.py +21 -0
  12. uipath_langchain/agent/guardrails/actions/__init__.py +11 -0
  13. uipath_langchain/agent/guardrails/actions/base_action.py +24 -0
  14. uipath_langchain/agent/guardrails/actions/block_action.py +42 -0
  15. uipath_langchain/agent/guardrails/actions/escalate_action.py +499 -0
  16. uipath_langchain/agent/guardrails/actions/log_action.py +58 -0
  17. uipath_langchain/agent/guardrails/guardrail_nodes.py +173 -0
  18. uipath_langchain/agent/guardrails/guardrails_factory.py +70 -0
  19. uipath_langchain/agent/guardrails/guardrails_subgraph.py +283 -0
  20. uipath_langchain/agent/guardrails/types.py +20 -0
  21. uipath_langchain/agent/react/__init__.py +14 -0
  22. uipath_langchain/agent/react/agent.py +117 -0
  23. uipath_langchain/agent/react/constants.py +2 -0
  24. uipath_langchain/agent/react/init_node.py +20 -0
  25. uipath_langchain/agent/react/llm_node.py +43 -0
  26. uipath_langchain/agent/react/router.py +97 -0
  27. uipath_langchain/agent/react/terminate_node.py +82 -0
  28. uipath_langchain/agent/react/tools/__init__.py +7 -0
  29. uipath_langchain/agent/react/tools/tools.py +50 -0
  30. uipath_langchain/agent/react/types.py +39 -0
  31. uipath_langchain/agent/react/utils.py +49 -0
  32. uipath_langchain/agent/tools/__init__.py +17 -0
  33. uipath_langchain/agent/tools/context_tool.py +53 -0
  34. uipath_langchain/agent/tools/escalation_tool.py +111 -0
  35. uipath_langchain/agent/tools/integration_tool.py +181 -0
  36. uipath_langchain/agent/tools/process_tool.py +49 -0
  37. uipath_langchain/agent/tools/static_args.py +138 -0
  38. uipath_langchain/agent/tools/structured_tool_with_output_type.py +14 -0
  39. uipath_langchain/agent/tools/tool_factory.py +45 -0
  40. uipath_langchain/agent/tools/tool_node.py +22 -0
  41. uipath_langchain/agent/tools/utils.py +11 -0
  42. uipath_langchain/chat/__init__.py +4 -0
  43. uipath_langchain/chat/bedrock.py +187 -0
  44. uipath_langchain/chat/mapper.py +309 -0
  45. uipath_langchain/chat/models.py +248 -35
  46. uipath_langchain/chat/openai.py +133 -0
  47. uipath_langchain/chat/supported_models.py +42 -0
  48. uipath_langchain/chat/vertex.py +255 -0
  49. uipath_langchain/embeddings/embeddings.py +131 -34
  50. uipath_langchain/middlewares.py +0 -6
  51. uipath_langchain/retrievers/context_grounding_retriever.py +7 -9
  52. uipath_langchain/runtime/__init__.py +36 -0
  53. uipath_langchain/runtime/_serialize.py +46 -0
  54. uipath_langchain/runtime/config.py +61 -0
  55. uipath_langchain/runtime/errors.py +43 -0
  56. uipath_langchain/runtime/factory.py +315 -0
  57. uipath_langchain/runtime/graph.py +159 -0
  58. uipath_langchain/runtime/runtime.py +453 -0
  59. uipath_langchain/runtime/schema.py +386 -0
  60. uipath_langchain/runtime/storage.py +115 -0
  61. uipath_langchain/vectorstores/context_grounding_vectorstore.py +90 -110
  62. {uipath_langchain-0.0.133.dist-info → uipath_langchain-0.1.28.dist-info}/METADATA +44 -23
  63. uipath_langchain-0.1.28.dist-info/RECORD +76 -0
  64. {uipath_langchain-0.0.133.dist-info → uipath_langchain-0.1.28.dist-info}/WHEEL +1 -1
  65. uipath_langchain-0.1.28.dist-info/entry_points.txt +5 -0
  66. uipath_langchain/_cli/_runtime/_context.py +0 -21
  67. uipath_langchain/_cli/_runtime/_conversation.py +0 -298
  68. uipath_langchain/_cli/_runtime/_exception.py +0 -17
  69. uipath_langchain/_cli/_runtime/_input.py +0 -139
  70. uipath_langchain/_cli/_runtime/_output.py +0 -234
  71. uipath_langchain/_cli/_runtime/_runtime.py +0 -379
  72. uipath_langchain/_cli/_utils/_graph.py +0 -199
  73. uipath_langchain/_cli/cli_dev.py +0 -44
  74. uipath_langchain/_cli/cli_eval.py +0 -78
  75. uipath_langchain/_cli/cli_run.py +0 -82
  76. uipath_langchain/_tracing/_oteladapter.py +0 -222
  77. uipath_langchain/_tracing/_utils.py +0 -28
  78. uipath_langchain/builder/agent_config.py +0 -191
  79. uipath_langchain/tools/preconfigured.py +0 -191
  80. uipath_langchain-0.0.133.dist-info/RECORD +0 -41
  81. uipath_langchain-0.0.133.dist-info/entry_points.txt +0 -2
  82. /uipath_langchain/{tools/__init__.py → py.typed} +0 -0
  83. {uipath_langchain-0.0.133.dist-info → uipath_langchain-0.1.28.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,386 @@
1
+ from dataclasses import dataclass
2
+ from typing import Any, Callable, TypeVar
3
+
4
+ from langchain_core.language_models.base import BaseLanguageModel
5
+ from langchain_core.language_models.chat_models import BaseChatModel
6
+ from langchain_core.runnables.base import Runnable
7
+ from langchain_core.runnables.graph import Graph, Node
8
+ from langgraph.graph.state import CompiledStateGraph
9
+ from langgraph.prebuilt import ToolNode
10
+ from langgraph.pregel._read import PregelNode
11
+ from langgraph.pregel._write import ChannelWrite, ChannelWriteEntry
12
+ from uipath.runtime.schema import (
13
+ UiPathRuntimeEdge,
14
+ UiPathRuntimeGraph,
15
+ UiPathRuntimeNode,
16
+ )
17
+
18
+ try:
19
+ from langgraph._internal._runnable import RunnableCallable
20
+ except ImportError:
21
+ RunnableCallable = None # type: ignore
22
+
23
+ T = TypeVar("T")
24
+
25
+
26
+ @dataclass
27
+ class SchemaDetails:
28
+ schema: dict[str, Any]
29
+ has_input_circular_dependency: bool
30
+ has_output_circular_dependency: bool
31
+
32
+
33
+ def _unwrap_runnable_callable(
34
+ runnable: Runnable[Any, Any], target_type: type[T]
35
+ ) -> T | None:
36
+ """Unwrap a RunnableCallable to find an instance of the target type.
37
+
38
+ Args:
39
+ runnable: The runnable to unwrap
40
+ target_type: The type to search for (e.g., BaseChatModel)
41
+
42
+ Returns:
43
+ Instance of target_type if found in the closure, None otherwise
44
+ """
45
+ if isinstance(runnable, target_type):
46
+ return runnable
47
+
48
+ if RunnableCallable is not None and isinstance(runnable, RunnableCallable):
49
+ func: Callable[..., Any] | None = getattr(runnable, "func", None)
50
+ if func is not None and hasattr(func, "__closure__") and func.__closure__:
51
+ for cell in func.__closure__:
52
+ if hasattr(cell, "cell_contents"):
53
+ content = cell.cell_contents
54
+ if isinstance(content, target_type):
55
+ return content
56
+
57
+ return None
58
+
59
+
60
+ def _get_node_type(node: Node) -> str:
61
+ """Determine the type of a LangGraph node using strongly-typed isinstance checks.
62
+
63
+ Args:
64
+ node: A Node object from the graph
65
+
66
+ Returns:
67
+ String representing the node type
68
+ """
69
+ if node.id in ("__start__", "__end__"):
70
+ return node.id
71
+
72
+ if node.data is None:
73
+ return "node"
74
+
75
+ if not isinstance(node.data, Runnable):
76
+ return "node"
77
+
78
+ tool_node = _unwrap_runnable_callable(node.data, ToolNode)
79
+ if tool_node is not None:
80
+ return "tool"
81
+
82
+ chat_model = _unwrap_runnable_callable(node.data, BaseChatModel) # type: ignore[type-abstract]
83
+ if chat_model is not None:
84
+ return "model"
85
+
86
+ language_model = _unwrap_runnable_callable(node.data, BaseLanguageModel) # type: ignore[type-abstract]
87
+ if language_model is not None:
88
+ return "model"
89
+
90
+ return "node"
91
+
92
+
93
+ def _get_node_metadata(node: Node) -> dict[str, Any]:
94
+ """Extract metadata from a node in a type-safe manner.
95
+
96
+ Args:
97
+ node: A Node object from the graph
98
+
99
+ Returns:
100
+ Dictionary containing node metadata
101
+ """
102
+ if node.data is None:
103
+ return {}
104
+
105
+ # Early return if data is not a Runnable
106
+ if not isinstance(node.data, Runnable):
107
+ return {}
108
+
109
+ metadata: dict[str, Any] = {}
110
+
111
+ tool_node = _unwrap_runnable_callable(node.data, ToolNode)
112
+ if tool_node is not None:
113
+ if hasattr(tool_node, "_tools_by_name"):
114
+ tools_by_name = tool_node._tools_by_name
115
+ metadata["tool_names"] = list(tools_by_name.keys())
116
+ metadata["tool_count"] = len(tools_by_name)
117
+ return metadata
118
+
119
+ chat_model = _unwrap_runnable_callable(node.data, BaseChatModel) # type: ignore[type-abstract]
120
+ if chat_model is not None:
121
+ if hasattr(chat_model, "model") and isinstance(chat_model.model, str):
122
+ metadata["model_name"] = chat_model.model
123
+ elif hasattr(chat_model, "model_name") and chat_model.model_name:
124
+ metadata["model_name"] = chat_model.model_name
125
+
126
+ if hasattr(chat_model, "temperature") and chat_model.temperature is not None:
127
+ metadata["temperature"] = chat_model.temperature
128
+
129
+ if hasattr(chat_model, "max_tokens") and chat_model.max_tokens is not None:
130
+ metadata["max_tokens"] = chat_model.max_tokens
131
+ elif (
132
+ hasattr(chat_model, "max_completion_tokens")
133
+ and chat_model.max_completion_tokens is not None
134
+ ):
135
+ metadata["max_tokens"] = chat_model.max_completion_tokens
136
+
137
+ return metadata
138
+
139
+
140
+ def _convert_graph_to_uipath(graph: Graph) -> UiPathRuntimeGraph:
141
+ """Helper to convert a LangGraph Graph object to UiPathRuntimeGraph.
142
+
143
+ Args:
144
+ graph: A LangGraph Graph object (from get_graph() call)
145
+
146
+ Returns:
147
+ UiPathRuntimeGraph with nodes and edges
148
+ """
149
+ nodes: list[UiPathRuntimeNode] = []
150
+ for _, node in graph.nodes.items():
151
+ nodes.append(
152
+ UiPathRuntimeNode(
153
+ id=node.id,
154
+ name=node.name or node.id,
155
+ type=_get_node_type(node),
156
+ metadata=_get_node_metadata(node),
157
+ subgraph=None,
158
+ )
159
+ )
160
+
161
+ edges: list[UiPathRuntimeEdge] = []
162
+ for edge in graph.edges:
163
+ edges.append(
164
+ UiPathRuntimeEdge(
165
+ source=edge.source,
166
+ target=edge.target,
167
+ label=getattr(edge, "data", None) or getattr(edge, "label", None),
168
+ )
169
+ )
170
+
171
+ return UiPathRuntimeGraph(nodes=nodes, edges=edges)
172
+
173
+
174
+ def get_graph_schema(
175
+ compiled_graph: CompiledStateGraph[Any, Any, Any, Any], xray: int = 1
176
+ ) -> UiPathRuntimeGraph:
177
+ """Convert a compiled LangGraph to UiPathRuntimeGraph structure.
178
+
179
+ Args:
180
+ compiled_graph: A compiled LangGraph (Pregel instance)
181
+ xray: Depth of subgraph expansion (0 = no subgraphs, 1 = one level, etc.)
182
+
183
+ Returns:
184
+ UiPathRuntimeGraph with hierarchical subgraph structure
185
+ """
186
+ graph: Graph = compiled_graph.get_graph(xray=0) # Keep parent at xray=0
187
+
188
+ subgraphs_dict: dict[str, UiPathRuntimeGraph] = {}
189
+ if xray:
190
+ for name, subgraph_pregel in compiled_graph.get_subgraphs():
191
+ next_xray: int = xray - 1 if isinstance(xray, int) and xray > 0 else 0
192
+ subgraph_graph: Graph = subgraph_pregel.get_graph(xray=next_xray)
193
+ subgraphs_dict[name] = _convert_graph_to_uipath(subgraph_graph)
194
+
195
+ nodes: list[UiPathRuntimeNode] = []
196
+ for node_id, node in graph.nodes.items():
197
+ subgraph: UiPathRuntimeGraph | None = subgraphs_dict.get(node_id)
198
+ nodes.append(
199
+ UiPathRuntimeNode(
200
+ id=node.id,
201
+ name=node.name or node.id,
202
+ type=_get_node_type(node),
203
+ metadata=_get_node_metadata(node),
204
+ subgraph=subgraph,
205
+ )
206
+ )
207
+
208
+ # Use a set to track unique edges (source, target)
209
+ seen_edges: set[tuple[str, str]] = set()
210
+ edges: list[UiPathRuntimeEdge] = []
211
+
212
+ # First, add edges from graph.edges (static edges)
213
+ for edge in graph.edges:
214
+ edge_tuple = (edge.source, edge.target)
215
+ if edge_tuple not in seen_edges:
216
+ seen_edges.add(edge_tuple)
217
+ edges.append(
218
+ UiPathRuntimeEdge(
219
+ source=edge.source,
220
+ target=edge.target,
221
+ label=getattr(edge, "data", None) or getattr(edge, "label", None),
222
+ )
223
+ )
224
+
225
+ # Build a map of channel -> target node
226
+ channel_to_target: dict[str, str] = {}
227
+ node_spec: PregelNode
228
+ for node_name, node_spec in compiled_graph.nodes.items():
229
+ for trigger in node_spec.triggers:
230
+ if isinstance(trigger, str) and trigger.startswith("branch:to:"):
231
+ channel_to_target[trigger] = node_name
232
+
233
+ # Extract edges by looking at what each node writes to (dynamic edges from Command)
234
+ for source_name, node_spec in compiled_graph.nodes.items():
235
+ writer: Runnable[Any, Any]
236
+ for writer in node_spec.writers:
237
+ if isinstance(writer, ChannelWrite):
238
+ write_entry: Any
239
+ for write_entry in writer.writes:
240
+ if isinstance(write_entry, ChannelWriteEntry) and isinstance(
241
+ write_entry.channel, str
242
+ ):
243
+ target = channel_to_target.get(write_entry.channel)
244
+ if target:
245
+ edge_tuple = (source_name, target)
246
+ if edge_tuple not in seen_edges:
247
+ seen_edges.add(edge_tuple)
248
+ edges.append(
249
+ UiPathRuntimeEdge(
250
+ source=source_name, target=target, label=None
251
+ )
252
+ )
253
+
254
+ return UiPathRuntimeGraph(nodes=nodes, edges=edges)
255
+
256
+
257
+ def get_entrypoints_schema(
258
+ graph: CompiledStateGraph[Any, Any, Any],
259
+ ) -> SchemaDetails:
260
+ """Extract input/output schema from a LangGraph graph"""
261
+ input_circular_dependency = False
262
+ output_circular_dependency = False
263
+ schema = {
264
+ "input": {"type": "object", "properties": {}, "required": []},
265
+ "output": {"type": "object", "properties": {}, "required": []},
266
+ }
267
+
268
+ if hasattr(graph, "input_schema"):
269
+ if hasattr(graph.input_schema, "model_json_schema"):
270
+ input_schema = graph.input_schema.model_json_schema()
271
+ unpacked_ref_def_properties, input_circular_dependency = _resolve_refs(
272
+ input_schema
273
+ )
274
+
275
+ # Process the schema to handle nullable types
276
+ processed_properties = _process_nullable_types(
277
+ unpacked_ref_def_properties.get("properties", {})
278
+ )
279
+
280
+ schema["input"]["properties"] = processed_properties
281
+ schema["input"]["required"] = unpacked_ref_def_properties.get(
282
+ "required", []
283
+ )
284
+
285
+ if hasattr(graph, "output_schema"):
286
+ if hasattr(graph.output_schema, "model_json_schema"):
287
+ output_schema = graph.output_schema.model_json_schema()
288
+ unpacked_ref_def_properties, output_circular_dependency = _resolve_refs(
289
+ output_schema
290
+ )
291
+
292
+ # Process the schema to handle nullable types
293
+ processed_properties = _process_nullable_types(
294
+ unpacked_ref_def_properties.get("properties", {})
295
+ )
296
+
297
+ schema["output"]["properties"] = processed_properties
298
+ schema["output"]["required"] = unpacked_ref_def_properties.get(
299
+ "required", []
300
+ )
301
+
302
+ return SchemaDetails(schema, input_circular_dependency, output_circular_dependency)
303
+
304
+
305
+ def _resolve_refs(schema, root=None, visited=None):
306
+ """Recursively resolves $ref references in a JSON schema, handling circular references.
307
+
308
+ Returns:
309
+ tuple: (resolved_schema, has_circular_dependency)
310
+ """
311
+ if root is None:
312
+ root = schema
313
+
314
+ if visited is None:
315
+ visited = set()
316
+
317
+ has_circular = False
318
+
319
+ if isinstance(schema, dict):
320
+ if "$ref" in schema:
321
+ ref_path = schema["$ref"]
322
+
323
+ if ref_path in visited:
324
+ # Circular dependency detected
325
+ return {
326
+ "type": "object",
327
+ "description": f"Circular reference to {ref_path}",
328
+ }, True
329
+
330
+ visited.add(ref_path)
331
+
332
+ # Resolve the reference
333
+ ref_parts = ref_path.lstrip("#/").split("/")
334
+ ref_schema = root
335
+ for part in ref_parts:
336
+ ref_schema = ref_schema.get(part, {})
337
+
338
+ result, circular = _resolve_refs(ref_schema, root, visited)
339
+ has_circular = has_circular or circular
340
+
341
+ # Remove from visited after resolution (allows the same ref in different branches)
342
+ visited.discard(ref_path)
343
+
344
+ return result, has_circular
345
+
346
+ resolved_dict = {}
347
+ for k, v in schema.items():
348
+ resolved_value, circular = _resolve_refs(v, root, visited)
349
+ resolved_dict[k] = resolved_value
350
+ has_circular = has_circular or circular
351
+ return resolved_dict, has_circular
352
+
353
+ elif isinstance(schema, list):
354
+ resolved_list = []
355
+ for item in schema:
356
+ resolved_item, circular = _resolve_refs(item, root, visited)
357
+ resolved_list.append(resolved_item)
358
+ has_circular = has_circular or circular
359
+ return resolved_list, has_circular
360
+
361
+ return schema, False
362
+
363
+
364
+ def _process_nullable_types(
365
+ schema: dict[str, Any] | list[Any] | Any,
366
+ ) -> dict[str, Any] | list[Any]:
367
+ """Process the schema to handle nullable types by removing anyOf with null and keeping the base type."""
368
+ if isinstance(schema, dict):
369
+ if "anyOf" in schema and len(schema["anyOf"]) == 2:
370
+ types = [t.get("type") for t in schema["anyOf"]]
371
+ if "null" in types:
372
+ non_null_type = next(
373
+ t for t in schema["anyOf"] if t.get("type") != "null"
374
+ )
375
+ return non_null_type
376
+
377
+ return {k: _process_nullable_types(v) for k, v in schema.items()}
378
+ elif isinstance(schema, list):
379
+ return [_process_nullable_types(item) for item in schema]
380
+ return schema
381
+
382
+
383
+ __all__ = [
384
+ "get_graph_schema",
385
+ "get_entrypoints_schema",
386
+ ]
@@ -0,0 +1,115 @@
1
+ """SQLite implementation of UiPathResumableStorageProtocol."""
2
+
3
+ import json
4
+ from typing import cast
5
+
6
+ from langgraph.checkpoint.sqlite.aio import AsyncSqliteSaver
7
+ from pydantic import BaseModel
8
+ from uipath.runtime import (
9
+ UiPathApiTrigger,
10
+ UiPathResumeTrigger,
11
+ UiPathResumeTriggerName,
12
+ UiPathResumeTriggerType,
13
+ )
14
+
15
+
16
+ class SqliteResumableStorage:
17
+ """SQLite storage for resume triggers."""
18
+
19
+ def __init__(
20
+ self, memory: AsyncSqliteSaver, table_name: str = "__uipath_resume_triggers"
21
+ ):
22
+ self.memory = memory
23
+ self.table_name = table_name
24
+ self._initialized = False
25
+
26
+ async def _ensure_table(self) -> None:
27
+ """Create table if needed."""
28
+ if self._initialized:
29
+ return
30
+
31
+ await self.memory.setup()
32
+ async with self.memory.lock, self.memory.conn.cursor() as cur:
33
+ await cur.execute(f"""
34
+ CREATE TABLE IF NOT EXISTS {self.table_name} (
35
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
36
+ type TEXT NOT NULL,
37
+ name TEXT NOT NULL,
38
+ key TEXT,
39
+ folder_key TEXT,
40
+ folder_path TEXT,
41
+ payload TEXT,
42
+ timestamp DATETIME DEFAULT (strftime('%Y-%m-%d %H:%M:%S', 'now', 'utc'))
43
+ )
44
+ """)
45
+ await self.memory.conn.commit()
46
+ self._initialized = True
47
+
48
+ async def save_trigger(self, trigger: UiPathResumeTrigger) -> None:
49
+ """Save resume trigger to database."""
50
+ await self._ensure_table()
51
+
52
+ trigger_key = (
53
+ trigger.api_resume.inbox_id if trigger.api_resume else trigger.item_key
54
+ )
55
+ payload = trigger.payload
56
+ if payload:
57
+ payload = (
58
+ (
59
+ payload.model_dump()
60
+ if isinstance(payload, BaseModel)
61
+ else json.dumps(payload)
62
+ )
63
+ if isinstance(payload, dict)
64
+ else str(payload)
65
+ )
66
+
67
+ async with self.memory.lock, self.memory.conn.cursor() as cur:
68
+ await cur.execute(
69
+ f"INSERT INTO {self.table_name} (type, key, name, payload, folder_path, folder_key) VALUES (?, ?, ?, ?, ?, ?)",
70
+ (
71
+ trigger.trigger_type.value,
72
+ trigger_key,
73
+ trigger.trigger_name.value,
74
+ payload,
75
+ trigger.folder_path,
76
+ trigger.folder_key,
77
+ ),
78
+ )
79
+ await self.memory.conn.commit()
80
+
81
+ async def get_latest_trigger(self) -> UiPathResumeTrigger | None:
82
+ """Get most recent trigger from database."""
83
+ await self._ensure_table()
84
+
85
+ async with self.memory.lock, self.memory.conn.cursor() as cur:
86
+ await cur.execute(f"""
87
+ SELECT type, key, name, folder_path, folder_key, payload
88
+ FROM {self.table_name}
89
+ ORDER BY timestamp DESC
90
+ LIMIT 1
91
+ """)
92
+ result = await cur.fetchone()
93
+
94
+ if not result:
95
+ return None
96
+
97
+ trigger_type, key, name, folder_path, folder_key, payload = cast(
98
+ tuple[str, str, str, str, str, str], tuple(result)
99
+ )
100
+
101
+ resume_trigger = UiPathResumeTrigger(
102
+ trigger_type=UiPathResumeTriggerType(trigger_type),
103
+ trigger_name=UiPathResumeTriggerName(name),
104
+ item_key=key,
105
+ folder_path=folder_path,
106
+ folder_key=folder_key,
107
+ payload=payload,
108
+ )
109
+
110
+ if resume_trigger.trigger_type == UiPathResumeTriggerType.API:
111
+ resume_trigger.api_resume = UiPathApiTrigger(
112
+ inbox_id=resume_trigger.item_key, request=resume_trigger.payload
113
+ )
114
+
115
+ return resume_trigger