Skip to content

Commit 359ffe1

Browse files
feat: add chat bridge protocol
1 parent 4a4868d commit 359ffe1

File tree

6 files changed

+373
-180
lines changed

6 files changed

+373
-180
lines changed

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "uipath-runtime"
3-
version = "0.2.0"
3+
version = "0.2.1"
44
description = "Runtime abstractions and interfaces for building agents and automation scripts in the UiPath ecosystem"
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"

src/uipath/runtime/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
UiPathStreamNotSupportedError,
88
UiPathStreamOptions,
99
)
10+
from uipath.runtime.chat.bridge import UiPathChatBridgeProtocol
11+
from uipath.runtime.chat.runtime import UiPathChatRuntime
1012
from uipath.runtime.context import UiPathRuntimeContext
1113
from uipath.runtime.debug.breakpoint import UiPathBreakpointResult
1214
from uipath.runtime.debug.bridge import UiPathDebugBridgeProtocol
@@ -66,4 +68,6 @@
6668
"UiPathBreakpointResult",
6769
"UiPathStreamNotSupportedError",
6870
"UiPathResumeTriggerName",
71+
"UiPathChatBridgeProtocol",
72+
"UiPathChatRuntime",
6973
]
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
"""Chat bridge protocol and runtime for conversational agents."""
2+
3+
from uipath.runtime.chat.bridge import UiPathChatBridgeProtocol
4+
from uipath.runtime.chat.runtime import UiPathChatRuntime
5+
6+
__all__ = ["UiPathChatBridgeProtocol", "UiPathChatRuntime"]

src/uipath/runtime/chat/bridge.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""Abstract conversation bridge interface."""
2+
3+
from typing import Any, Protocol
4+
5+
6+
class UiPathChatBridgeProtocol(Protocol):
7+
"""Abstract interface for chat communication.
8+
9+
Implementations: WebSocket, etc.
10+
"""
11+
12+
async def connect(self) -> None:
13+
"""Establish connection to chat service."""
14+
...
15+
16+
async def disconnect(self) -> None:
17+
"""Close connection and send exchange end event."""
18+
...
19+
20+
async def emit_message_event(self, message_event: Any) -> None:
21+
"""Wrap and send a message event.
22+
23+
Args:
24+
message_event: UiPathConversationMessageEvent to wrap and send
25+
"""
26+
...

src/uipath/runtime/chat/runtime.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
"""Chat runtime implementation."""
2+
3+
import logging
4+
from typing import Any, AsyncGenerator, cast
5+
6+
from uipath.runtime.base import (
7+
UiPathExecuteOptions,
8+
UiPathRuntimeProtocol,
9+
UiPathStreamNotSupportedError,
10+
UiPathStreamOptions,
11+
)
12+
from uipath.runtime.chat.bridge import UiPathChatBridgeProtocol
13+
from uipath.runtime.events import (
14+
UiPathRuntimeEvent,
15+
UiPathRuntimeMessageEvent,
16+
)
17+
from uipath.runtime.result import (
18+
UiPathRuntimeResult,
19+
UiPathRuntimeStatus,
20+
)
21+
from uipath.runtime.schema import UiPathRuntimeSchema
22+
23+
logger = logging.getLogger(__name__)
24+
25+
26+
class UiPathChatRuntime:
27+
"""Specialized runtime for chat mode that streams message events to a chat bridge."""
28+
29+
def __init__(
30+
self,
31+
delegate: UiPathRuntimeProtocol,
32+
chat_bridge: UiPathChatBridgeProtocol,
33+
):
34+
"""Initialize the UiPathChatRuntime.
35+
36+
Args:
37+
delegate: The underlying runtime to wrap
38+
chat_bridge: Bridge for chat event communication
39+
"""
40+
super().__init__()
41+
self.delegate = delegate
42+
self.chat_bridge = chat_bridge
43+
44+
async def execute(
45+
self,
46+
input: dict[str, Any] | None = None,
47+
options: UiPathExecuteOptions | None = None,
48+
) -> UiPathRuntimeResult:
49+
"""Execute the workflow with chat support."""
50+
result: UiPathRuntimeResult | None = None
51+
async for event in self.stream(input, cast(UiPathStreamOptions, options)):
52+
if isinstance(event, UiPathRuntimeResult):
53+
result = event
54+
55+
return (
56+
result
57+
if result
58+
else UiPathRuntimeResult(status=UiPathRuntimeStatus.SUCCESSFUL)
59+
)
60+
61+
async def stream(
62+
self,
63+
input: dict[str, Any] | None = None,
64+
options: UiPathStreamOptions | None = None,
65+
) -> AsyncGenerator[UiPathRuntimeEvent, None]:
66+
"""Stream execution events with chat support."""
67+
await self.chat_bridge.connect()
68+
69+
result: UiPathRuntimeResult | None = None
70+
71+
async for event in self.delegate.stream(input, options=options):
72+
# Send message events to chat bridge
73+
if isinstance(event, UiPathRuntimeMessageEvent):
74+
if event.payload:
75+
await self.chat_bridge.emit_message_event(event.payload)
76+
77+
yield event
78+
79+
if isinstance(event, UiPathRuntimeResult):
80+
result = event
81+
82+
if result:
83+
logger.info(f"Chat execution completed with status: {result.status}")
84+
85+
# Always disconnect from chat bridge
86+
await self.chat_bridge.disconnect()
87+
88+
async def get_schema(self) -> UiPathRuntimeSchema:
89+
"""Get schema from the delegate runtime."""
90+
return await self.delegate.get_schema()
91+
92+
async def dispose(self) -> None:
93+
"""Dispose the delegate runtime."""
94+
await self.delegate.dispose()

0 commit comments

Comments
 (0)