uipath 2.1.36__py3-none-any.whl → 2.1.38__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.
- uipath/_cli/_dev/_terminal/__init__.py +70 -31
- uipath/_cli/_dev/_terminal/_components/_chat.py +106 -0
- uipath/_cli/_dev/_terminal/_components/_details.py +31 -15
- uipath/_cli/_dev/_terminal/_components/_history.py +16 -0
- uipath/_cli/_dev/_terminal/_models/_execution.py +16 -3
- uipath/_cli/_dev/_terminal/_models/_messages.py +3 -2
- uipath/_cli/_dev/_terminal/_styles/terminal.tcss +30 -2
- uipath/_cli/_dev/_terminal/_utils/_chat.py +240 -0
- uipath/_cli/_dev/_terminal/{_traces → _utils}/_logger.py +3 -3
- uipath/_cli/_runtime/_contracts.py +14 -0
- uipath/_cli/cli_dev.py +31 -7
- uipath/_cli/cli_init.py +3 -1
- uipath/agent/conversation/__init__.py +135 -0
- uipath/agent/conversation/async_stream.py +54 -0
- uipath/agent/conversation/citation.py +70 -0
- uipath/agent/conversation/content.py +81 -0
- uipath/agent/conversation/conversation.py +49 -0
- uipath/agent/conversation/event.py +56 -0
- uipath/agent/conversation/exchange.py +61 -0
- uipath/agent/conversation/message.py +59 -0
- uipath/agent/conversation/meta.py +11 -0
- uipath/agent/conversation/tool.py +64 -0
- {uipath-2.1.36.dist-info → uipath-2.1.38.dist-info}/METADATA +2 -1
- {uipath-2.1.36.dist-info → uipath-2.1.38.dist-info}/RECORD +28 -17
- uipath/_cli/_dev/_terminal/_components/_resume.py +0 -35
- /uipath/_cli/_dev/_terminal/{_traces → _utils}/_exporter.py +0 -0
- {uipath-2.1.36.dist-info → uipath-2.1.38.dist-info}/WHEEL +0 -0
- {uipath-2.1.36.dist-info → uipath-2.1.38.dist-info}/entry_points.txt +0 -0
- {uipath-2.1.36.dist-info → uipath-2.1.38.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,240 @@
|
|
1
|
+
import uuid
|
2
|
+
from datetime import datetime
|
3
|
+
from typing import Callable, Dict, Optional
|
4
|
+
|
5
|
+
from uipath.agent.conversation import (
|
6
|
+
UiPathConversationContentPart,
|
7
|
+
UiPathConversationContentPartChunkEvent,
|
8
|
+
UiPathConversationContentPartEndEvent,
|
9
|
+
UiPathConversationContentPartEvent,
|
10
|
+
UiPathConversationContentPartStartEvent,
|
11
|
+
UiPathConversationEvent,
|
12
|
+
UiPathConversationExchangeEvent,
|
13
|
+
UiPathConversationMessage,
|
14
|
+
UiPathConversationMessageEndEvent,
|
15
|
+
UiPathConversationMessageEvent,
|
16
|
+
UiPathConversationMessageStartEvent,
|
17
|
+
UiPathConversationToolCall,
|
18
|
+
UiPathConversationToolCallResult,
|
19
|
+
UiPathInlineValue,
|
20
|
+
)
|
21
|
+
|
22
|
+
from ...._runtime._contracts import UiPathConversationHandler
|
23
|
+
|
24
|
+
|
25
|
+
class RunContextChatHandler(UiPathConversationHandler):
|
26
|
+
"""Custom chat handler that sends chat messages to CLI UI."""
|
27
|
+
|
28
|
+
def __init__(
|
29
|
+
self,
|
30
|
+
run_id: str,
|
31
|
+
callback: Callable[[UiPathConversationEvent, str], None],
|
32
|
+
):
|
33
|
+
super().__init__()
|
34
|
+
self.run_id = run_id
|
35
|
+
self.callback = callback
|
36
|
+
|
37
|
+
def on_event(self, event: UiPathConversationEvent) -> None:
|
38
|
+
"""Handle a chat message for a given execution run."""
|
39
|
+
self.callback(event, self.run_id)
|
40
|
+
|
41
|
+
|
42
|
+
class ConversationAggregator:
|
43
|
+
"""Incrementally builds messages from UiPathConversationEvents."""
|
44
|
+
|
45
|
+
messages: Dict[str, UiPathConversationMessage]
|
46
|
+
|
47
|
+
def __init__(self) -> None:
|
48
|
+
self.messages = {}
|
49
|
+
|
50
|
+
def add_event(
|
51
|
+
self, event: UiPathConversationEvent
|
52
|
+
) -> Optional[UiPathConversationMessage]:
|
53
|
+
"""Process an incoming conversation-level event and return the current message snapshot if applicable."""
|
54
|
+
if not event.exchange or not event.exchange.message:
|
55
|
+
return None
|
56
|
+
|
57
|
+
msg_event = event.exchange.message
|
58
|
+
return self._process_message_event(msg_event)
|
59
|
+
|
60
|
+
def _process_message_event(
|
61
|
+
self, ev: UiPathConversationMessageEvent
|
62
|
+
) -> UiPathConversationMessage:
|
63
|
+
msg = self.messages.get(ev.message_id)
|
64
|
+
|
65
|
+
if not msg:
|
66
|
+
# Initialize message on first sighting
|
67
|
+
msg = UiPathConversationMessage(
|
68
|
+
message_id=ev.message_id,
|
69
|
+
role=self._infer_role(ev),
|
70
|
+
content_parts=[],
|
71
|
+
tool_calls=[],
|
72
|
+
created_at=self._timestamp(ev),
|
73
|
+
updated_at=self._timestamp(ev),
|
74
|
+
)
|
75
|
+
self.messages[ev.message_id] = msg
|
76
|
+
|
77
|
+
# --- Handle content parts (text, JSON, etc.) ---
|
78
|
+
if ev.content_part:
|
79
|
+
cp_event = ev.content_part
|
80
|
+
|
81
|
+
existing = next(
|
82
|
+
(
|
83
|
+
cp
|
84
|
+
for cp in (msg.content_parts or [])
|
85
|
+
if cp.content_part_id == cp_event.content_part_id
|
86
|
+
),
|
87
|
+
None,
|
88
|
+
)
|
89
|
+
|
90
|
+
# Start of a new content part
|
91
|
+
if cp_event.start and not existing:
|
92
|
+
new_cp = UiPathConversationContentPart(
|
93
|
+
content_part_id=cp_event.content_part_id,
|
94
|
+
mime_type=cp_event.start.mime_type,
|
95
|
+
data=UiPathInlineValue(inline=""),
|
96
|
+
citations=[],
|
97
|
+
is_transcript=None,
|
98
|
+
is_incomplete=True,
|
99
|
+
)
|
100
|
+
if msg.content_parts is None:
|
101
|
+
msg.content_parts = []
|
102
|
+
msg.content_parts.append(new_cp)
|
103
|
+
existing = new_cp
|
104
|
+
|
105
|
+
# Chunk for an existing part (or backfill if start missing)
|
106
|
+
if cp_event.chunk:
|
107
|
+
if not existing:
|
108
|
+
new_cp = UiPathConversationContentPart(
|
109
|
+
content_part_id=cp_event.content_part_id,
|
110
|
+
mime_type="text/plain", # fallback if start missing
|
111
|
+
data=UiPathInlineValue(inline=""),
|
112
|
+
citations=[],
|
113
|
+
is_transcript=None,
|
114
|
+
is_incomplete=True,
|
115
|
+
)
|
116
|
+
if msg.content_parts is None:
|
117
|
+
msg.content_parts = []
|
118
|
+
msg.content_parts.append(new_cp)
|
119
|
+
existing = new_cp
|
120
|
+
|
121
|
+
if isinstance(existing.data, UiPathInlineValue):
|
122
|
+
existing.data.inline += cp_event.chunk.data or ""
|
123
|
+
|
124
|
+
# End of a part
|
125
|
+
if cp_event.end and existing:
|
126
|
+
existing.is_incomplete = bool(cp_event.end.interrupted)
|
127
|
+
|
128
|
+
# --- Handle tool calls ---
|
129
|
+
if ev.tool_call:
|
130
|
+
tc_event = ev.tool_call
|
131
|
+
existing_tool_call = next(
|
132
|
+
(
|
133
|
+
tc
|
134
|
+
for tc in (msg.tool_calls or [])
|
135
|
+
if tc.tool_call_id == tc_event.tool_call_id
|
136
|
+
),
|
137
|
+
None,
|
138
|
+
)
|
139
|
+
|
140
|
+
# Start of a tool call
|
141
|
+
if tc_event.start:
|
142
|
+
if not existing_tool_call:
|
143
|
+
new_tc = UiPathConversationToolCall(
|
144
|
+
tool_call_id=tc_event.tool_call_id,
|
145
|
+
name=tc_event.start.tool_name,
|
146
|
+
arguments=None, # args will arrive as JSON content part
|
147
|
+
timestamp=tc_event.start.timestamp,
|
148
|
+
result=None,
|
149
|
+
)
|
150
|
+
if msg.tool_calls is None:
|
151
|
+
msg.tool_calls = []
|
152
|
+
msg.tool_calls.append(new_tc)
|
153
|
+
existing_tool_call = new_tc
|
154
|
+
else:
|
155
|
+
existing_tool_call.name = (
|
156
|
+
tc_event.start.tool_name or existing_tool_call.name
|
157
|
+
)
|
158
|
+
existing_tool_call.timestamp = (
|
159
|
+
tc_event.start.timestamp or existing_tool_call.timestamp
|
160
|
+
)
|
161
|
+
|
162
|
+
# End of a tool call
|
163
|
+
if tc_event.end:
|
164
|
+
if not existing_tool_call:
|
165
|
+
existing_tool_call = UiPathConversationToolCall(
|
166
|
+
tool_call_id=tc_event.tool_call_id,
|
167
|
+
name="", # unknown until start seen
|
168
|
+
arguments=None,
|
169
|
+
)
|
170
|
+
if msg.tool_calls is None:
|
171
|
+
msg.tool_calls = []
|
172
|
+
msg.tool_calls.append(existing_tool_call)
|
173
|
+
|
174
|
+
existing_tool_call.result = UiPathConversationToolCallResult(
|
175
|
+
timestamp=tc_event.end.timestamp,
|
176
|
+
value=tc_event.end.result,
|
177
|
+
is_error=tc_event.end.is_error,
|
178
|
+
cancelled=tc_event.end.cancelled,
|
179
|
+
)
|
180
|
+
|
181
|
+
# --- Update timestamps ---
|
182
|
+
msg.updated_at = self._timestamp(ev)
|
183
|
+
return msg
|
184
|
+
|
185
|
+
def _timestamp(self, ev: UiPathConversationMessageEvent) -> str:
|
186
|
+
"""Choose timestamp from event if available, else fallback."""
|
187
|
+
if ev.start and ev.start.timestamp:
|
188
|
+
return ev.start.timestamp
|
189
|
+
return datetime.now().isoformat()
|
190
|
+
|
191
|
+
def _infer_role(self, ev: UiPathConversationMessageEvent) -> str:
|
192
|
+
if ev.start and ev.start.role:
|
193
|
+
return ev.start.role
|
194
|
+
return "assistant"
|
195
|
+
|
196
|
+
|
197
|
+
def build_user_message_event(
|
198
|
+
user_text: str, conversation_id: str, role: str = "user"
|
199
|
+
) -> UiPathConversationEvent:
|
200
|
+
message_id = str(uuid.uuid4())
|
201
|
+
content_part_id = str(uuid.uuid4())
|
202
|
+
timestamp = datetime.now().isoformat()
|
203
|
+
|
204
|
+
# Build message start
|
205
|
+
msg_start = UiPathConversationMessageStartEvent(
|
206
|
+
role=role,
|
207
|
+
timestamp=timestamp,
|
208
|
+
)
|
209
|
+
|
210
|
+
# Build content part (simple one-shot inline text)
|
211
|
+
cp_start = UiPathConversationContentPartStartEvent(mime_type="text/plain")
|
212
|
+
cp_chunk = UiPathConversationContentPartChunkEvent(data=user_text)
|
213
|
+
cp_end = UiPathConversationContentPartEndEvent()
|
214
|
+
|
215
|
+
content_event = UiPathConversationContentPartEvent(
|
216
|
+
content_part_id=content_part_id,
|
217
|
+
start=cp_start,
|
218
|
+
chunk=cp_chunk,
|
219
|
+
end=cp_end,
|
220
|
+
)
|
221
|
+
|
222
|
+
# Build message event
|
223
|
+
msg_event = UiPathConversationMessageEvent(
|
224
|
+
message_id=message_id,
|
225
|
+
start=msg_start,
|
226
|
+
content_part=content_event,
|
227
|
+
end=UiPathConversationMessageEndEvent(),
|
228
|
+
)
|
229
|
+
|
230
|
+
# Wrap in exchange event
|
231
|
+
exch_event = UiPathConversationExchangeEvent(
|
232
|
+
exchange_id=str(uuid.uuid4()),
|
233
|
+
message=msg_event,
|
234
|
+
)
|
235
|
+
|
236
|
+
# Finally wrap in conversation event
|
237
|
+
conv_event = UiPathConversationEvent(
|
238
|
+
exchange=exch_event, conversation_id=conversation_id
|
239
|
+
)
|
240
|
+
return conv_event
|
@@ -11,11 +11,11 @@ class RunContextLogHandler(logging.Handler):
|
|
11
11
|
def __init__(
|
12
12
|
self,
|
13
13
|
run_id: str,
|
14
|
-
|
14
|
+
callback: Callable[[LogMessage], None],
|
15
15
|
):
|
16
16
|
super().__init__()
|
17
17
|
self.run_id = run_id
|
18
|
-
self.
|
18
|
+
self.callback = callback
|
19
19
|
|
20
20
|
def emit(self, record: logging.LogRecord):
|
21
21
|
"""Emit a log record to CLI UI."""
|
@@ -26,7 +26,7 @@ class RunContextLogHandler(logging.Handler):
|
|
26
26
|
message=self.format(record),
|
27
27
|
timestamp=datetime.fromtimestamp(record.created),
|
28
28
|
)
|
29
|
-
self.
|
29
|
+
self.callback(log_msg)
|
30
30
|
except Exception:
|
31
31
|
# Don't let logging errors crash the app
|
32
32
|
pass
|
@@ -22,6 +22,7 @@ from opentelemetry.sdk.trace.export import (
|
|
22
22
|
from opentelemetry.trace import Tracer
|
23
23
|
from pydantic import BaseModel, Field
|
24
24
|
|
25
|
+
from uipath.agent.conversation import UiPathConversationEvent
|
25
26
|
from uipath.tracing import TracingManager
|
26
27
|
|
27
28
|
from ._logging import LogsInterceptor
|
@@ -134,6 +135,17 @@ class UiPathRuntimeResult(BaseModel):
|
|
134
135
|
return result
|
135
136
|
|
136
137
|
|
138
|
+
class UiPathConversationHandler(ABC):
|
139
|
+
"""Base delegate for handling UiPath conversation events."""
|
140
|
+
|
141
|
+
use_streaming: bool = True
|
142
|
+
|
143
|
+
@abstractmethod
|
144
|
+
def on_event(self, event: UiPathConversationEvent) -> None:
|
145
|
+
"""Handle a conversation event for a given execution run."""
|
146
|
+
pass
|
147
|
+
|
148
|
+
|
137
149
|
class UiPathTraceContext(BaseModel):
|
138
150
|
"""Trace context information for tracing and debugging."""
|
139
151
|
|
@@ -173,6 +185,8 @@ class UiPathRuntimeContext(BaseModel):
|
|
173
185
|
input_file: Optional[str] = None
|
174
186
|
is_eval_run: bool = False
|
175
187
|
log_handler: Optional[logging.Handler] = None
|
188
|
+
chat_handler: Optional[UiPathConversationHandler] = None
|
189
|
+
|
176
190
|
model_config = {"arbitrary_types_allowed": True}
|
177
191
|
|
178
192
|
@classmethod
|
uipath/_cli/cli_dev.py
CHANGED
@@ -1,23 +1,47 @@
|
|
1
1
|
import asyncio
|
2
|
+
import os
|
2
3
|
from typing import Optional
|
3
4
|
|
4
5
|
import click
|
5
6
|
|
6
|
-
from
|
7
|
-
from .
|
8
|
-
from ._runtime.
|
9
|
-
from .
|
10
|
-
from ._utils.
|
11
|
-
from .
|
7
|
+
from uipath._cli._dev._terminal import UiPathDevTerminal
|
8
|
+
from uipath._cli._runtime._contracts import UiPathRuntimeContext, UiPathRuntimeFactory
|
9
|
+
from uipath._cli._runtime._runtime import UiPathRuntime
|
10
|
+
from uipath._cli._utils._console import ConsoleLogger
|
11
|
+
from uipath._cli._utils._debug import setup_debugging
|
12
|
+
from uipath._cli.cli_init import init # type: ignore[attr-defined]
|
13
|
+
from uipath._cli.middlewares import Middlewares
|
14
|
+
from uipath.telemetry import track
|
12
15
|
|
13
16
|
console = ConsoleLogger()
|
14
17
|
|
15
18
|
|
16
19
|
@click.command()
|
17
20
|
@click.argument("interface", default="terminal")
|
21
|
+
@click.option(
|
22
|
+
"--debug",
|
23
|
+
is_flag=True,
|
24
|
+
help="Enable debugging with debugpy. The process will wait for a debugger to attach.",
|
25
|
+
)
|
26
|
+
@click.option(
|
27
|
+
"--debug-port",
|
28
|
+
type=int,
|
29
|
+
default=5678,
|
30
|
+
help="Port for the debug server (default: 5678)",
|
31
|
+
)
|
18
32
|
@track
|
19
|
-
def dev(interface: Optional[str]) -> None:
|
33
|
+
def dev(interface: Optional[str], debug: bool, debug_port: int) -> None:
|
20
34
|
"""Launch interactive debugging interface."""
|
35
|
+
project_file = os.path.join(os.getcwd(), "uipath.json")
|
36
|
+
|
37
|
+
if not os.path.exists(project_file):
|
38
|
+
console.warning("Project not initialized. Running `uipath init`...")
|
39
|
+
ctx = click.get_current_context()
|
40
|
+
ctx.invoke(init)
|
41
|
+
|
42
|
+
if not setup_debugging(debug, debug_port):
|
43
|
+
console.error(f"Failed to start debug server on port {debug_port}")
|
44
|
+
|
21
45
|
console.info("Launching UiPath debugging terminal ...")
|
22
46
|
result = Middlewares.next(
|
23
47
|
"dev",
|
uipath/_cli/cli_init.py
CHANGED
@@ -90,7 +90,9 @@ def get_user_script(directory: str, entrypoint: Optional[str] = None) -> Optiona
|
|
90
90
|
python_files = [f for f in os.listdir(directory) if f.endswith(".py")]
|
91
91
|
|
92
92
|
if not python_files:
|
93
|
-
console.error(
|
93
|
+
console.error(
|
94
|
+
"No python files found in the current directory.\nPlease specify the entrypoint: `uipath init <entrypoint_path>`"
|
95
|
+
)
|
94
96
|
return None
|
95
97
|
elif len(python_files) == 1:
|
96
98
|
return os.path.join(directory, python_files[0])
|
@@ -0,0 +1,135 @@
|
|
1
|
+
"""UiPath Conversation Models.
|
2
|
+
|
3
|
+
This module provides Pydantic models that represent the JSON event schema for conversations between a client (UI) and an LLM/agent.
|
4
|
+
|
5
|
+
The event objects define a hierarchal conversation structure:
|
6
|
+
|
7
|
+
* Conversation
|
8
|
+
* Exchange
|
9
|
+
* Message
|
10
|
+
* Content Parts
|
11
|
+
* Citations
|
12
|
+
* Tool Calls
|
13
|
+
* Tool Results
|
14
|
+
|
15
|
+
A conversation may contain multiple exchanges, and an exchange may contain multiple messages. A message may contain
|
16
|
+
multiple content parts, each of which can be text or binary, including media input and output streams; and each
|
17
|
+
content part can include multiple citations. A message may also contain multiple tool calls, which may contain a tool
|
18
|
+
result.
|
19
|
+
|
20
|
+
The protocol also supports a top level, "async", input media streams (audio and video), which can span multiple
|
21
|
+
exchanges. These are used for Gemini's automatic turn detection mode, where the LLM determines when the user has
|
22
|
+
stopped talking and starts producing output. The output forms one or more messages in an exchange with no explicit
|
23
|
+
input message. However, the LLM may produce an input transcript which can be used to construct the implicit input
|
24
|
+
message that started the exchange.
|
25
|
+
|
26
|
+
In addition, the protocol also supports "async" tool calls that span multiple exchanges. This can be used with
|
27
|
+
Gemini's asynchronous function calling protocol, which allows function calls to produce results that interrupt the
|
28
|
+
conversation when ready, even after multiple exchanges. They also support generating multiple results from a single
|
29
|
+
tool call. By contrast most tool calls are scoped to a single message, which contains both the call and the single
|
30
|
+
result produced by that call.
|
31
|
+
|
32
|
+
Not all features supported by the protocol will be supported by all clients and LLMs. The optional top level
|
33
|
+
`capabilities` property can be used to communicate information about supported features. This property should be set
|
34
|
+
on the first event written to a new websocket connection. This initial event may or may not contain additional
|
35
|
+
sub-events.
|
36
|
+
"""
|
37
|
+
|
38
|
+
from .async_stream import (
|
39
|
+
UiPathConversationAsyncInputStreamEndEvent,
|
40
|
+
UiPathConversationAsyncInputStreamEvent,
|
41
|
+
UiPathConversationAsyncInputStreamStartEvent,
|
42
|
+
UiPathConversationInputStreamChunkEvent,
|
43
|
+
)
|
44
|
+
from .citation import (
|
45
|
+
UiPathConversationCitationEndEvent,
|
46
|
+
UiPathConversationCitationEvent,
|
47
|
+
UiPathConversationCitationSource,
|
48
|
+
UiPathConversationCitationSourceMedia,
|
49
|
+
UiPathConversationCitationSourceUrl,
|
50
|
+
UiPathConversationCitationStartEvent,
|
51
|
+
)
|
52
|
+
from .content import (
|
53
|
+
UiPathConversationContentPart,
|
54
|
+
UiPathConversationContentPartChunkEvent,
|
55
|
+
UiPathConversationContentPartEndEvent,
|
56
|
+
UiPathConversationContentPartEvent,
|
57
|
+
UiPathConversationContentPartStartEvent,
|
58
|
+
UiPathExternalValue,
|
59
|
+
UiPathInlineValue,
|
60
|
+
)
|
61
|
+
from .conversation import (
|
62
|
+
UiPathConversationCapabilities,
|
63
|
+
UiPathConversationEndEvent,
|
64
|
+
UiPathConversationStartedEvent,
|
65
|
+
UiPathConversationStartEvent,
|
66
|
+
)
|
67
|
+
from .event import UiPathConversationEvent
|
68
|
+
from .exchange import (
|
69
|
+
UiPathConversationExchange,
|
70
|
+
UiPathConversationExchangeEndEvent,
|
71
|
+
UiPathConversationExchangeEvent,
|
72
|
+
UiPathConversationExchangeStartEvent,
|
73
|
+
)
|
74
|
+
from .message import (
|
75
|
+
UiPathConversationMessage,
|
76
|
+
UiPathConversationMessageEndEvent,
|
77
|
+
UiPathConversationMessageEvent,
|
78
|
+
UiPathConversationMessageStartEvent,
|
79
|
+
)
|
80
|
+
from .meta import UiPathConversationMetaEvent
|
81
|
+
from .tool import (
|
82
|
+
UiPathConversationToolCall,
|
83
|
+
UiPathConversationToolCallEndEvent,
|
84
|
+
UiPathConversationToolCallEvent,
|
85
|
+
UiPathConversationToolCallResult,
|
86
|
+
UiPathConversationToolCallStartEvent,
|
87
|
+
)
|
88
|
+
|
89
|
+
__all__ = [
|
90
|
+
# Root
|
91
|
+
"UiPathConversationEvent",
|
92
|
+
# Conversation
|
93
|
+
"UiPathConversationCapabilities",
|
94
|
+
"UiPathConversationStartEvent",
|
95
|
+
"UiPathConversationStartedEvent",
|
96
|
+
"UiPathConversationEndEvent",
|
97
|
+
# Exchange
|
98
|
+
"UiPathConversationExchangeStartEvent",
|
99
|
+
"UiPathConversationExchangeEndEvent",
|
100
|
+
"UiPathConversationExchangeEvent",
|
101
|
+
"UiPathConversationExchange",
|
102
|
+
# Message
|
103
|
+
"UiPathConversationMessageStartEvent",
|
104
|
+
"UiPathConversationMessageEndEvent",
|
105
|
+
"UiPathConversationMessageEvent",
|
106
|
+
"UiPathConversationMessage",
|
107
|
+
# Content
|
108
|
+
"UiPathConversationContentPartChunkEvent",
|
109
|
+
"UiPathConversationContentPartStartEvent",
|
110
|
+
"UiPathConversationContentPartEndEvent",
|
111
|
+
"UiPathConversationContentPartEvent",
|
112
|
+
"UiPathConversationContentPart",
|
113
|
+
"UiPathInlineValue",
|
114
|
+
"UiPathExternalValue",
|
115
|
+
# Citation
|
116
|
+
"UiPathConversationCitationStartEvent",
|
117
|
+
"UiPathConversationCitationEndEvent",
|
118
|
+
"UiPathConversationCitationEvent",
|
119
|
+
"UiPathConversationCitationSource",
|
120
|
+
"UiPathConversationCitationSourceUrl",
|
121
|
+
"UiPathConversationCitationSourceMedia",
|
122
|
+
# Tool
|
123
|
+
"UiPathConversationToolCallStartEvent",
|
124
|
+
"UiPathConversationToolCallEndEvent",
|
125
|
+
"UiPathConversationToolCallEvent",
|
126
|
+
"UiPathConversationToolCallResult",
|
127
|
+
"UiPathConversationToolCall",
|
128
|
+
# Async Stream
|
129
|
+
"UiPathConversationInputStreamChunkEvent",
|
130
|
+
"UiPathConversationAsyncInputStreamStartEvent",
|
131
|
+
"UiPathConversationAsyncInputStreamEndEvent",
|
132
|
+
"UiPathConversationAsyncInputStreamEvent",
|
133
|
+
# Meta
|
134
|
+
"UiPathConversationMetaEvent",
|
135
|
+
]
|
@@ -0,0 +1,54 @@
|
|
1
|
+
"""Async input stream events."""
|
2
|
+
|
3
|
+
from typing import Any, Dict, Optional
|
4
|
+
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field
|
6
|
+
|
7
|
+
|
8
|
+
class UiPathConversationInputStreamChunkEvent(BaseModel):
|
9
|
+
"""Represents a single chunk of input stream data."""
|
10
|
+
|
11
|
+
input_stream_sequence: Optional[int] = Field(None, alias="inputStreamSequence")
|
12
|
+
data: str
|
13
|
+
|
14
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
15
|
+
|
16
|
+
|
17
|
+
class UiPathConversationAsyncInputStreamStartEvent(BaseModel):
|
18
|
+
"""Signals the start of an asynchronous input stream."""
|
19
|
+
|
20
|
+
mime_type: str = Field(..., alias="mimeType")
|
21
|
+
start_of_speech_sensitivity: Optional[str] = Field(
|
22
|
+
None, alias="startOfSpeechSensitivity"
|
23
|
+
)
|
24
|
+
end_of_speech_sensitivity: Optional[str] = Field(
|
25
|
+
None, alias="endOfSpeechSensitivity"
|
26
|
+
)
|
27
|
+
prefix_padding_ms: Optional[int] = Field(None, alias="prefixPaddingMs")
|
28
|
+
silence_duration_ms: Optional[int] = Field(None, alias="silenceDurationMs")
|
29
|
+
meta_data: Optional[Dict[str, Any]] = Field(None, alias="metaData")
|
30
|
+
|
31
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
32
|
+
|
33
|
+
|
34
|
+
class UiPathConversationAsyncInputStreamEndEvent(BaseModel):
|
35
|
+
"""Signals the end of an asynchronous input stream."""
|
36
|
+
|
37
|
+
meta_data: Optional[Dict[str, Any]] = Field(None, alias="metaData")
|
38
|
+
last_chunk_content_part_sequence: Optional[int] = Field(
|
39
|
+
None, alias="lastChunkContentPartSequence"
|
40
|
+
)
|
41
|
+
|
42
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
43
|
+
|
44
|
+
|
45
|
+
class UiPathConversationAsyncInputStreamEvent(BaseModel):
|
46
|
+
"""Encapsulates sub-events related to an asynchronous input stream."""
|
47
|
+
|
48
|
+
stream_id: str = Field(..., alias="streamId")
|
49
|
+
start: Optional[UiPathConversationAsyncInputStreamStartEvent] = None
|
50
|
+
end: Optional[UiPathConversationAsyncInputStreamEndEvent] = None
|
51
|
+
chunk: Optional[UiPathConversationInputStreamChunkEvent] = None
|
52
|
+
meta_event: Optional[Dict[str, Any]] = Field(None, alias="metaEvent")
|
53
|
+
|
54
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
@@ -0,0 +1,70 @@
|
|
1
|
+
"""Citation events for message content."""
|
2
|
+
|
3
|
+
from typing import Any, Dict, List, Optional
|
4
|
+
|
5
|
+
from pydantic import BaseModel, ConfigDict, Field
|
6
|
+
|
7
|
+
|
8
|
+
class UiPathConversationCitationStartEvent(BaseModel):
|
9
|
+
"""Indicates the start of a citation target in a content part."""
|
10
|
+
|
11
|
+
pass
|
12
|
+
|
13
|
+
|
14
|
+
class UiPathConversationCitationEndEvent(BaseModel):
|
15
|
+
"""Indicates the end of a citation target in a content part."""
|
16
|
+
|
17
|
+
sources: List[Dict[str, Any]]
|
18
|
+
|
19
|
+
|
20
|
+
class UiPathConversationCitationEvent(BaseModel):
|
21
|
+
"""Encapsulates sub-events related to citations."""
|
22
|
+
|
23
|
+
citation_id: str = Field(..., alias="citationId")
|
24
|
+
start: Optional[UiPathConversationCitationStartEvent] = None
|
25
|
+
end: Optional[UiPathConversationCitationEndEvent] = None
|
26
|
+
|
27
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
28
|
+
|
29
|
+
|
30
|
+
class UiPathConversationCitationSourceUrl(BaseModel):
|
31
|
+
"""Represents a citation source that can be rendered as a link (URL)."""
|
32
|
+
|
33
|
+
url: str
|
34
|
+
|
35
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
36
|
+
|
37
|
+
|
38
|
+
class UiPathConversationCitationSourceMedia(BaseModel):
|
39
|
+
"""Represents a citation source that references media, such as a PDF document."""
|
40
|
+
|
41
|
+
mime_type: str = Field(..., alias="mimeType")
|
42
|
+
download_url: Optional[str] = Field(None, alias="downloadUrl")
|
43
|
+
page_number: Optional[str] = Field(None, alias="pageNumber")
|
44
|
+
|
45
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
46
|
+
|
47
|
+
|
48
|
+
class UiPathConversationCitationSource(BaseModel):
|
49
|
+
"""Represents a citation source, either a URL or media reference."""
|
50
|
+
|
51
|
+
title: Optional[str] = None
|
52
|
+
|
53
|
+
# Union of Url or Media
|
54
|
+
url: Optional[str] = None
|
55
|
+
mime_type: Optional[str] = Field(None, alias="mimeType")
|
56
|
+
download_url: Optional[str] = Field(None, alias="downloadUrl")
|
57
|
+
page_number: Optional[str] = Field(None, alias="pageNumber")
|
58
|
+
|
59
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|
60
|
+
|
61
|
+
|
62
|
+
class UiPathConversationCitation(BaseModel):
|
63
|
+
"""Represents a citation or reference inside a content part."""
|
64
|
+
|
65
|
+
citation_id: str = Field(..., alias="citationId")
|
66
|
+
offset: int
|
67
|
+
length: int
|
68
|
+
sources: List[UiPathConversationCitationSource]
|
69
|
+
|
70
|
+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
|