uipath-langchain 0.0.112__py3-none-any.whl → 0.1.24__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 (82) hide show
  1. uipath_langchain/_cli/_templates/main.py.template +12 -13
  2. uipath_langchain/_cli/cli_init.py +127 -156
  3. uipath_langchain/_cli/cli_new.py +2 -6
  4. uipath_langchain/_resources/AGENTS.md +21 -0
  5. uipath_langchain/_resources/REQUIRED_STRUCTURE.md +92 -0
  6. uipath_langchain/{tracers → _tracing}/__init__.py +0 -2
  7. uipath_langchain/_tracing/_instrument_traceable.py +134 -0
  8. uipath_langchain/_utils/__init__.py +1 -2
  9. uipath_langchain/_utils/_request_mixin.py +351 -54
  10. uipath_langchain/_utils/_settings.py +2 -11
  11. uipath_langchain/agent/exceptions/__init__.py +6 -0
  12. uipath_langchain/agent/exceptions/exceptions.py +11 -0
  13. uipath_langchain/agent/guardrails/__init__.py +21 -0
  14. uipath_langchain/agent/guardrails/actions/__init__.py +11 -0
  15. uipath_langchain/agent/guardrails/actions/base_action.py +23 -0
  16. uipath_langchain/agent/guardrails/actions/block_action.py +41 -0
  17. uipath_langchain/agent/guardrails/actions/escalate_action.py +274 -0
  18. uipath_langchain/agent/guardrails/actions/log_action.py +57 -0
  19. uipath_langchain/agent/guardrails/guardrail_nodes.py +125 -0
  20. uipath_langchain/agent/guardrails/guardrails_factory.py +70 -0
  21. uipath_langchain/agent/guardrails/guardrails_subgraph.py +247 -0
  22. uipath_langchain/agent/guardrails/types.py +20 -0
  23. uipath_langchain/agent/react/__init__.py +14 -0
  24. uipath_langchain/agent/react/agent.py +113 -0
  25. uipath_langchain/agent/react/constants.py +2 -0
  26. uipath_langchain/agent/react/init_node.py +20 -0
  27. uipath_langchain/agent/react/llm_node.py +43 -0
  28. uipath_langchain/agent/react/router.py +97 -0
  29. uipath_langchain/agent/react/terminate_node.py +82 -0
  30. uipath_langchain/agent/react/tools/__init__.py +7 -0
  31. uipath_langchain/agent/react/tools/tools.py +50 -0
  32. uipath_langchain/agent/react/types.py +39 -0
  33. uipath_langchain/agent/react/utils.py +49 -0
  34. uipath_langchain/agent/tools/__init__.py +17 -0
  35. uipath_langchain/agent/tools/context_tool.py +53 -0
  36. uipath_langchain/agent/tools/escalation_tool.py +111 -0
  37. uipath_langchain/agent/tools/integration_tool.py +181 -0
  38. uipath_langchain/agent/tools/process_tool.py +49 -0
  39. uipath_langchain/agent/tools/static_args.py +138 -0
  40. uipath_langchain/agent/tools/structured_tool_with_output_type.py +14 -0
  41. uipath_langchain/agent/tools/tool_factory.py +45 -0
  42. uipath_langchain/agent/tools/tool_node.py +22 -0
  43. uipath_langchain/agent/tools/utils.py +11 -0
  44. uipath_langchain/chat/__init__.py +4 -0
  45. uipath_langchain/chat/bedrock.py +187 -0
  46. uipath_langchain/chat/gemini.py +330 -0
  47. uipath_langchain/chat/mapper.py +309 -0
  48. uipath_langchain/chat/models.py +261 -38
  49. uipath_langchain/chat/openai.py +132 -0
  50. uipath_langchain/chat/supported_models.py +42 -0
  51. uipath_langchain/embeddings/embeddings.py +136 -36
  52. uipath_langchain/middlewares.py +0 -2
  53. uipath_langchain/py.typed +0 -0
  54. uipath_langchain/retrievers/context_grounding_retriever.py +7 -9
  55. uipath_langchain/runtime/__init__.py +36 -0
  56. uipath_langchain/runtime/_serialize.py +46 -0
  57. uipath_langchain/runtime/config.py +61 -0
  58. uipath_langchain/runtime/errors.py +43 -0
  59. uipath_langchain/runtime/factory.py +315 -0
  60. uipath_langchain/runtime/graph.py +159 -0
  61. uipath_langchain/runtime/runtime.py +453 -0
  62. uipath_langchain/runtime/schema.py +349 -0
  63. uipath_langchain/runtime/storage.py +115 -0
  64. uipath_langchain/vectorstores/context_grounding_vectorstore.py +90 -110
  65. {uipath_langchain-0.0.112.dist-info → uipath_langchain-0.1.24.dist-info}/METADATA +42 -20
  66. uipath_langchain-0.1.24.dist-info/RECORD +76 -0
  67. {uipath_langchain-0.0.112.dist-info → uipath_langchain-0.1.24.dist-info}/WHEEL +1 -1
  68. uipath_langchain-0.1.24.dist-info/entry_points.txt +5 -0
  69. uipath_langchain/_cli/_runtime/_context.py +0 -21
  70. uipath_langchain/_cli/_runtime/_exception.py +0 -17
  71. uipath_langchain/_cli/_runtime/_input.py +0 -136
  72. uipath_langchain/_cli/_runtime/_output.py +0 -234
  73. uipath_langchain/_cli/_runtime/_runtime.py +0 -371
  74. uipath_langchain/_cli/_utils/_graph.py +0 -202
  75. uipath_langchain/_cli/cli_run.py +0 -80
  76. uipath_langchain/tracers/AsyncUiPathTracer.py +0 -274
  77. uipath_langchain/tracers/_events.py +0 -33
  78. uipath_langchain/tracers/_instrument_traceable.py +0 -416
  79. uipath_langchain/tracers/_utils.py +0 -52
  80. uipath_langchain-0.0.112.dist-info/RECORD +0 -36
  81. uipath_langchain-0.0.112.dist-info/entry_points.txt +0 -2
  82. {uipath_langchain-0.0.112.dist-info → uipath_langchain-0.1.24.dist-info}/licenses/LICENSE +0 -0
@@ -1,136 +0,0 @@
1
- import logging
2
- from typing import Any, Optional, cast
3
-
4
- from langgraph.types import Command
5
- from uipath import UiPath
6
- from uipath._cli._runtime._contracts import (
7
- UiPathApiTrigger,
8
- UiPathErrorCategory,
9
- UiPathResumeTrigger,
10
- UiPathResumeTriggerType,
11
- )
12
- from uipath._cli._runtime._hitl import HitlReader
13
-
14
- from ._context import LangGraphRuntimeContext
15
- from ._exception import LangGraphRuntimeError
16
-
17
- logger = logging.getLogger(__name__)
18
-
19
-
20
- class LangGraphInputProcessor:
21
- """
22
- Handles input processing for graph execution, including resume scenarios
23
- where it needs to fetch data from UiPath.
24
- """
25
-
26
- def __init__(self, context: LangGraphRuntimeContext):
27
- """
28
- Initialize the LangGraphInputProcessor.
29
-
30
- Args:
31
- context: The runtime context for the graph execution.
32
- """
33
- self.context = context
34
- self.uipath = UiPath()
35
-
36
- async def process(self) -> Any:
37
- """
38
- Process the input data for graph execution, handling both fresh starts and resume scenarios.
39
-
40
- This method determines whether the graph is being executed fresh or resumed from a previous state.
41
- For fresh executions, it returns the input JSON directly. For resume scenarios, it fetches
42
- the latest trigger information from the database and constructs a Command object with the
43
- appropriate resume data.
44
-
45
- The method handles different types of resume triggers:
46
- - API triggers: Creates an UiPathApiTrigger with inbox_id and request payload
47
- - Other triggers: Uses the HitlReader to process the resume data
48
-
49
- Returns:
50
- Any: For fresh executions, returns the input JSON data directly.
51
- For resume scenarios, returns a Command object containing the resume data
52
- processed through the appropriate trigger handler.
53
-
54
- Raises:
55
- LangGraphRuntimeError: If there's an error fetching trigger data from the database
56
- during resume processing.
57
- """
58
- logger.debug(f"Resumed: {self.context.resume} Input: {self.context.input_json}")
59
-
60
- if not self.context.resume:
61
- return self.context.input_json
62
-
63
- if self.context.input_json:
64
- return Command(resume=self.context.input_json)
65
-
66
- trigger = await self._get_latest_trigger()
67
- if not trigger:
68
- return Command(resume=self.context.input_json)
69
-
70
- trigger_type, key, folder_path, folder_key, payload = trigger
71
- resume_trigger = UiPathResumeTrigger(
72
- trigger_type=trigger_type,
73
- item_key=key,
74
- folder_path=folder_path,
75
- folder_key=folder_key,
76
- payload=payload,
77
- )
78
- logger.debug(f"ResumeTrigger: {trigger_type} {key}")
79
-
80
- # populate back expected fields for api_triggers
81
- if resume_trigger.trigger_type == UiPathResumeTriggerType.API:
82
- resume_trigger.api_resume = UiPathApiTrigger(
83
- inbox_id=resume_trigger.item_key, request=resume_trigger.payload
84
- )
85
- return Command(resume=await HitlReader.read(resume_trigger))
86
-
87
- async def _get_latest_trigger(self) -> Optional[tuple[str, str, str, str, str]]:
88
- """
89
- Fetch the most recent resume trigger from the database.
90
-
91
- This private method queries the resume triggers table to retrieve the latest trigger
92
- information based on timestamp. It handles database connection setup and executes
93
- a SQL query to fetch trigger data needed for resume operations.
94
-
95
- The method returns trigger information as a tuple containing:
96
- - type: The type of trigger (e.g., 'API', 'MANUAL', etc.)
97
- - key: The unique identifier for the trigger/item
98
- - folder_path: The path to the folder containing the trigger
99
- - folder_key: The unique identifier for the folder
100
- - payload: The serialized payload data associated with the trigger
101
-
102
- Returns:
103
- Optional[tuple[str, str, str, str, str]]: A tuple containing (type, key, folder_path,
104
- folder_key, payload) for the most recent trigger, or None if no triggers are found
105
- or if the memory context is not available.
106
-
107
- Raises:
108
- LangGraphRuntimeError: If there's an error during database connection setup, query
109
- execution, or result fetching. The original exception is wrapped with context
110
- about the database operation failure.
111
- """
112
- if self.context.memory is None:
113
- return None
114
- try:
115
- await self.context.memory.setup()
116
- async with (
117
- self.context.memory.lock,
118
- self.context.memory.conn.cursor() as cur,
119
- ):
120
- await cur.execute(f"""
121
- SELECT type, key, folder_path, folder_key, payload
122
- FROM {self.context.resume_triggers_table}
123
- ORDER BY timestamp DESC
124
- LIMIT 1
125
- """)
126
- result = await cur.fetchone()
127
- if result is None:
128
- return None
129
- return cast(tuple[str, str, str, str, str], tuple(result))
130
- except Exception as e:
131
- raise LangGraphRuntimeError(
132
- "DB_QUERY_FAILED",
133
- "Database query failed",
134
- f"Error querying resume trigger information: {str(e)}",
135
- UiPathErrorCategory.SYSTEM,
136
- ) from e
@@ -1,234 +0,0 @@
1
- import json
2
- import logging
3
- from functools import cached_property
4
- from typing import Any, Dict, Optional, cast
5
-
6
- from langgraph.types import Interrupt, StateSnapshot
7
- from uipath._cli._runtime._contracts import (
8
- UiPathErrorCategory,
9
- UiPathResumeTrigger,
10
- UiPathRuntimeResult,
11
- UiPathRuntimeStatus,
12
- )
13
- from uipath._cli._runtime._hitl import HitlProcessor
14
-
15
- from ._context import LangGraphRuntimeContext
16
- from ._exception import LangGraphRuntimeError
17
-
18
- logger = logging.getLogger(__name__)
19
-
20
-
21
- class LangGraphOutputProcessor:
22
- """
23
- Contains and manages the complete output information from graph execution.
24
- Handles serialization, interrupt data, and file output.
25
- """
26
-
27
- def __init__(self, context: LangGraphRuntimeContext) -> None:
28
- """
29
- Initialize the LangGraphOutputProcessor.
30
-
31
- Args:
32
- context: The runtime context for the graph execution.
33
- """
34
- self.context = context
35
- self._hitl_processor: Optional[HitlProcessor] = None
36
- self._resume_trigger: Optional[UiPathResumeTrigger] = None
37
-
38
- @classmethod
39
- async def create(
40
- cls, context: LangGraphRuntimeContext
41
- ) -> "LangGraphOutputProcessor":
42
- """
43
- Create and initialize a new LangGraphOutputProcessor instance asynchronously.
44
-
45
- Args:
46
- context: The runtime context for the graph execution.
47
-
48
- Returns:
49
- LangGraphOutputProcessor: A new initialized instance.
50
- """
51
- instance = cls(context)
52
-
53
- # Process interrupt information during initialization
54
- state = cast(StateSnapshot, context.state)
55
- if not state or not hasattr(state, "next") or not state.next:
56
- return instance
57
-
58
- for task in state.tasks:
59
- if hasattr(task, "interrupts") and task.interrupts:
60
- for interrupt in task.interrupts:
61
- if isinstance(interrupt, Interrupt):
62
- instance._hitl_processor = HitlProcessor(interrupt.value)
63
- return instance
64
-
65
- return instance
66
-
67
- @property
68
- def status(self) -> UiPathRuntimeStatus:
69
- """Determines the execution status based on state."""
70
- return (
71
- UiPathRuntimeStatus.SUSPENDED
72
- if self._hitl_processor
73
- else UiPathRuntimeStatus.SUCCESSFUL
74
- )
75
-
76
- @cached_property
77
- def serialized_output(self) -> Dict[str, Any]:
78
- """Serializes the graph execution result."""
79
- try:
80
- if self.context.output is None:
81
- return {}
82
-
83
- return self._serialize_object(self.context.output)
84
-
85
- except Exception as e:
86
- raise LangGraphRuntimeError(
87
- "OUTPUT_SERIALIZATION_FAILED",
88
- "Failed to serialize graph output",
89
- f"Error serializing output data: {str(e)}",
90
- UiPathErrorCategory.SYSTEM,
91
- ) from e
92
-
93
- def _serialize_object(self, obj):
94
- """Recursively serializes an object and all its nested components."""
95
- # Handle Pydantic models
96
- if hasattr(obj, "dict"):
97
- return self._serialize_object(obj.dict())
98
- elif hasattr(obj, "model_dump"):
99
- return self._serialize_object(obj.model_dump(by_alias=True))
100
- elif hasattr(obj, "to_dict"):
101
- return self._serialize_object(obj.to_dict())
102
- # Handle dictionaries
103
- elif isinstance(obj, dict):
104
- return {k: self._serialize_object(v) for k, v in obj.items()}
105
- # Handle lists
106
- elif isinstance(obj, list):
107
- return [self._serialize_object(item) for item in obj]
108
- # Handle other iterable objects (convert to dict first)
109
- elif hasattr(obj, "__iter__") and not isinstance(obj, (str, bytes)):
110
- try:
111
- return self._serialize_object(dict(obj))
112
- except (TypeError, ValueError):
113
- return obj
114
- # Return primitive types as is
115
- else:
116
- return obj
117
-
118
- async def process(self) -> UiPathRuntimeResult:
119
- """
120
- Process the output and prepare the final execution result.
121
-
122
- Returns:
123
- UiPathRuntimeResult: The processed execution result.
124
-
125
- Raises:
126
- LangGraphRuntimeError: If processing fails.
127
- """
128
- try:
129
- await self._save_resume_trigger()
130
-
131
- return UiPathRuntimeResult(
132
- output=self.serialized_output,
133
- status=self.status,
134
- resume=self._resume_trigger if self._resume_trigger else None,
135
- )
136
-
137
- except LangGraphRuntimeError:
138
- raise
139
- except Exception as e:
140
- raise LangGraphRuntimeError(
141
- "OUTPUT_PROCESSING_FAILED",
142
- "Failed to process execution output",
143
- f"Unexpected error during output processing: {str(e)}",
144
- UiPathErrorCategory.SYSTEM,
145
- ) from e
146
-
147
- async def _save_resume_trigger(self) -> None:
148
- """
149
- Stores the resume trigger in the SQLite database if available.
150
-
151
- Raises:
152
- LangGraphRuntimeError: If database operations fail.
153
- """
154
- if not self._hitl_processor or not self.context.memory:
155
- return
156
-
157
- try:
158
- await self.context.memory.setup()
159
- async with (
160
- self.context.memory.lock,
161
- self.context.memory.conn.cursor() as cur,
162
- ):
163
- try:
164
- await cur.execute(f"""
165
- CREATE TABLE IF NOT EXISTS {self.context.resume_triggers_table} (
166
- id INTEGER PRIMARY KEY AUTOINCREMENT,
167
- type TEXT NOT NULL,
168
- key TEXT,
169
- folder_key TEXT,
170
- folder_path TEXT,
171
- payload TEXT,
172
- timestamp DATETIME DEFAULT (strftime('%Y-%m-%d %H:%M:%S', 'now', 'utc'))
173
- )
174
- """)
175
- except Exception as e:
176
- raise LangGraphRuntimeError(
177
- "DB_TABLE_CREATION_FAILED",
178
- "Failed to create resume triggers table",
179
- f"Database error while creating table: {str(e)}",
180
- UiPathErrorCategory.SYSTEM,
181
- ) from e
182
-
183
- try:
184
- self._resume_trigger = (
185
- await self._hitl_processor.create_resume_trigger()
186
- )
187
- except Exception as e:
188
- raise LangGraphRuntimeError(
189
- "HITL_EVENT_CREATION_FAILED",
190
- "Failed to process HITL request",
191
- f"Error while trying to process HITL request: {str(e)}",
192
- UiPathErrorCategory.SYSTEM,
193
- ) from e
194
- # if API trigger, override item_key and payload
195
- if self._resume_trigger:
196
- if self._resume_trigger.api_resume:
197
- trigger_key = self._resume_trigger.api_resume.inbox_id
198
- else:
199
- trigger_key = self._resume_trigger.item_key
200
- try:
201
- logger.debug(
202
- f"ResumeTrigger: {self._resume_trigger.trigger_type} {self._resume_trigger.item_key}"
203
- )
204
- if isinstance(self._resume_trigger.payload, dict):
205
- payload = json.dumps(self._resume_trigger.payload)
206
- else:
207
- payload = str(self._resume_trigger.payload)
208
- await cur.execute(
209
- f"INSERT INTO {self.context.resume_triggers_table} (type, key, payload, folder_path, folder_key) VALUES (?, ?, ?, ?, ?)",
210
- (
211
- self._resume_trigger.trigger_type.value,
212
- trigger_key,
213
- payload,
214
- self._resume_trigger.folder_path,
215
- self._resume_trigger.folder_key,
216
- ),
217
- )
218
- await self.context.memory.conn.commit()
219
- except Exception as e:
220
- raise LangGraphRuntimeError(
221
- "DB_INSERT_FAILED",
222
- "Failed to save resume trigger",
223
- f"Database error while saving resume trigger: {str(e)}",
224
- UiPathErrorCategory.SYSTEM,
225
- ) from e
226
- except LangGraphRuntimeError:
227
- raise
228
- except Exception as e:
229
- raise LangGraphRuntimeError(
230
- "RESUME_TRIGGER_SAVE_FAILED",
231
- "Failed to save resume trigger",
232
- f"Unexpected error while saving resume trigger: {str(e)}",
233
- UiPathErrorCategory.SYSTEM,
234
- ) from e