Skip to content
This repository was archived by the owner on Mar 4, 2026. It is now read-only.

Commit 013ba17

Browse files
Merge pull request #16 from UiPath/fix/fix-citation-source-on-event-model
fix: fix citation source on event model and add error & interrupt models
2 parents 424f696 + d564fc3 commit 013ba17

12 files changed

Lines changed: 151 additions & 13 deletions

File tree

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-core"
3-
version = "0.1.0"
3+
version = "0.1.1"
44
description = "UiPath Core abstractions"
55
readme = { file = "README.md", content-type = "text/markdown" }
66
requires-python = ">=3.11"

src/uipath/core/chat/__init__.py

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,23 @@
6666
UiPathConversationStartedEvent,
6767
UiPathConversationStartEvent,
6868
)
69-
from .event import UiPathConversationEvent
69+
from .error import (
70+
UiPathConversationErrorEndEvent,
71+
UiPathConversationErrorEvent,
72+
UiPathConversationErrorStartEvent,
73+
)
74+
from .event import UiPathConversationEvent, UiPathConversationLabelUpdatedEvent
7075
from .exchange import (
7176
UiPathConversationExchange,
7277
UiPathConversationExchangeEndEvent,
7378
UiPathConversationExchangeEvent,
7479
UiPathConversationExchangeStartEvent,
7580
)
81+
from .interrupt import (
82+
UiPathConversationInterruptEndEvent,
83+
UiPathConversationInterruptEvent,
84+
UiPathConversationInterruptStartEvent,
85+
)
7686
from .message import (
7787
UiPathConversationMessage,
7888
UiPathConversationMessageEndEvent,
@@ -91,6 +101,11 @@
91101
__all__ = [
92102
# Root
93103
"UiPathConversationEvent",
104+
"UiPathConversationLabelUpdatedEvent",
105+
# Error
106+
"UiPathConversationErrorStartEvent",
107+
"UiPathConversationErrorEndEvent",
108+
"UiPathConversationErrorEvent",
94109
# Conversation
95110
"UiPathConversationCapabilities",
96111
"UiPathConversationStartEvent",
@@ -106,6 +121,10 @@
106121
"UiPathConversationMessageEndEvent",
107122
"UiPathConversationMessageEvent",
108123
"UiPathConversationMessage",
124+
# Interrupt
125+
"UiPathConversationInterruptStartEvent",
126+
"UiPathConversationInterruptEndEvent",
127+
"UiPathConversationInterruptEvent",
109128
# Content
110129
"UiPathConversationContentPartChunkEvent",
111130
"UiPathConversationContentPartStartEvent",

src/uipath/core/chat/async_stream.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,12 @@
44

55
from pydantic import BaseModel, ConfigDict, Field
66

7+
from .error import UiPathConversationErrorEvent
8+
79

810
class UiPathConversationInputStreamChunkEvent(BaseModel):
911
"""Represents a single chunk of input stream data."""
1012

11-
input_stream_sequence: int | None = Field(None, alias="inputStreamSequence")
1213
data: str
1314

1415
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
@@ -44,9 +45,16 @@ class UiPathConversationAsyncInputStreamEvent(BaseModel):
4445
"""Encapsulates sub-events related to an asynchronous input stream."""
4546

4647
stream_id: str = Field(..., alias="streamId")
47-
start: UiPathConversationAsyncInputStreamStartEvent | None = None
48-
end: UiPathConversationAsyncInputStreamEndEvent | None = None
48+
start: UiPathConversationAsyncInputStreamStartEvent | None = Field(
49+
None, alias="startAsyncInputStream"
50+
)
51+
end: UiPathConversationAsyncInputStreamEndEvent | None = Field(
52+
None, alias="endAsyncInputStream"
53+
)
4954
chunk: UiPathConversationInputStreamChunkEvent | None = None
5055
meta_event: dict[str, Any] | None = Field(None, alias="metaEvent")
56+
error: UiPathConversationErrorEvent | None = Field(
57+
None, alias="asyncInputStreamError"
58+
)
5159

5260
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)

src/uipath/core/chat/citation.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
"""Citation events for message content."""
22

3-
from typing import Any
3+
from __future__ import annotations
44

55
from pydantic import BaseModel, ConfigDict, Field
66

7+
from .error import UiPathConversationErrorEvent
8+
79

810
class UiPathConversationCitationStartEvent(BaseModel):
911
"""Indicates the start of a citation target in a content part."""
@@ -14,7 +16,7 @@ class UiPathConversationCitationStartEvent(BaseModel):
1416
class UiPathConversationCitationEndEvent(BaseModel):
1517
"""Indicates the end of a citation target in a content part."""
1618

17-
sources: list[dict[str, Any]]
19+
sources: list[UiPathConversationCitationSource]
1820

1921
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
2022

@@ -27,6 +29,7 @@ class UiPathConversationCitationEvent(BaseModel):
2729
None, alias="startCitation"
2830
)
2931
end: UiPathConversationCitationEndEvent | None = Field(None, alias="endCitation")
32+
error: UiPathConversationErrorEvent | None = Field(None, alias="citationError")
3033

3134
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
3235

@@ -52,9 +55,10 @@ class UiPathConversationCitationSourceMedia(BaseModel):
5255
class UiPathConversationCitationSource(BaseModel):
5356
"""Represents a citation source, either a URL or media reference."""
5457

55-
title: str | None = None
58+
title: str
59+
number: int
5660

57-
# Union of Url or Media
61+
# Union of Url or Media - these are optional
5862
url: str | None = None
5963
mime_type: str | None = Field(None, alias="mimeType")
6064
download_url: str | None = Field(None, alias="downloadUrl")

src/uipath/core/chat/content.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from pydantic import BaseModel, ConfigDict, Field
66

77
from .citation import UiPathConversationCitation, UiPathConversationCitationEvent
8+
from .error import UiPathConversationErrorEvent
89

910

1011
class UiPathConversationContentPartChunkEvent(BaseModel):
@@ -21,6 +22,9 @@ class UiPathConversationContentPartStartEvent(BaseModel):
2122

2223
mime_type: str = Field(..., alias="mimeType")
2324
metadata: dict[str, Any] | None = Field(None, alias="metaData")
25+
external_value: "UiPathExternalValue | None" = Field(None, alias="externalValue")
26+
name: str | None = None
27+
timestamp: str | None = None
2428

2529
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
2630

@@ -49,6 +53,7 @@ class UiPathConversationContentPartEvent(BaseModel):
4953
)
5054
chunk: UiPathConversationContentPartChunkEvent | None = None
5155
meta_event: dict[str, Any] | None = Field(None, alias="metaEvent")
56+
error: UiPathConversationErrorEvent | None = Field(None, alias="contentPartError")
5257

5358
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
5459

@@ -64,7 +69,7 @@ class UiPathInlineValue(BaseModel):
6469
class UiPathExternalValue(BaseModel):
6570
"""Used when a value is too large to be returned inline."""
6671

67-
url: str
72+
uri: str
6873
byte_count: int | None = Field(None, alias="byteCount")
6974

7075
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)

src/uipath/core/chat/error.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""Common error event models used across all conversation event types."""
2+
3+
from typing import Any
4+
5+
from pydantic import BaseModel, ConfigDict, Field
6+
7+
8+
class UiPathConversationErrorStartEvent(BaseModel):
9+
"""Represents the start of an error condition."""
10+
11+
message: str
12+
details: Any | None = None
13+
14+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
15+
16+
17+
class UiPathConversationErrorEndEvent(BaseModel):
18+
"""Represents the end of an error condition."""
19+
20+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
21+
22+
23+
class UiPathConversationErrorEvent(BaseModel):
24+
"""Encapsulates sub-events that represent the start and end of an error condition.
25+
26+
This is a common error event model used across all event types (conversation, exchange,
27+
message, content part, citation, tool call, async input stream).
28+
"""
29+
30+
error_id: str = Field(..., alias="errorId")
31+
start: UiPathConversationErrorStartEvent | None = Field(None, alias="startError")
32+
end: UiPathConversationErrorEndEvent | None = Field(None, alias="endError")
33+
34+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)

src/uipath/core/chat/event.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,21 @@
1212
UiPathConversationStartedEvent,
1313
UiPathConversationStartEvent,
1414
)
15+
from .error import UiPathConversationErrorEvent
1516
from .exchange import UiPathConversationExchangeEvent
1617
from .meta import UiPathConversationMetaEvent
1718
from .tool import UiPathConversationToolCallEvent
1819

1920

21+
class UiPathConversationLabelUpdatedEvent(BaseModel):
22+
"""Indicates the update of the conversation label."""
23+
24+
label: str
25+
autogenerated: bool
26+
27+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
28+
29+
2030
class UiPathConversationEvent(BaseModel):
2131
"""The top-level event type representing an event in a conversation.
2232
@@ -31,13 +41,17 @@ class UiPathConversationEvent(BaseModel):
3141
)
3242
start: UiPathConversationStartEvent | None = Field(
3343
None,
44+
alias="startSession",
3445
description="Signals the start of an event stream concerning a conversation. This event does NOT necessarily mean this is a brand new conversation. It may be a continuation of an existing conversation.",
3546
)
3647
started: UiPathConversationStartedEvent | None = Field(
37-
None, description="Signals the acceptance of the start of a conversation."
48+
None,
49+
alias="sessionStarted",
50+
description="Signals the acceptance of the start of a conversation.",
3851
)
3952
end: UiPathConversationEndEvent | None = Field(
4053
None,
54+
alias="endSession",
4155
description="Signals the end of a conversation event stream. This does NOT mean the conversation is over. A new event stream for the conversation could be started in the future.",
4256
)
4357
exchange: UiPathConversationExchangeEvent | None = Field(
@@ -54,10 +68,20 @@ class UiPathConversationEvent(BaseModel):
5468
alias="asyncToolCall",
5569
description="Optional async tool call sub-event. This feature is not supported by all LLMs. Most tool calls are scoped to a message, and use the toolCall and toolResult properties defined by the ConversationMessage type.",
5670
)
71+
label_updated: "UiPathConversationLabelUpdatedEvent | None" = Field(
72+
None,
73+
alias="labelUpdated",
74+
description="Indicates that the conversation's label has been updated. Useful for UIs to update the display name of live conversations.",
75+
)
5776
meta_event: UiPathConversationMetaEvent | None = Field(
5877
None,
5978
alias="metaEvent",
6079
description="Allows additional events to be sent in the context of the enclosing event stream.",
6180
)
81+
error: UiPathConversationErrorEvent | None = Field(
82+
None,
83+
alias="conversationError",
84+
description="Sent by the service to indicate the start and end of an error condition impacting a conversation. The client should not send any events for this conversation while the error condition is present.",
85+
)
6286

6387
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)

src/uipath/core/chat/exchange.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
from pydantic import BaseModel, ConfigDict, Field
2222

23+
from .error import UiPathConversationErrorEvent
2324
from .message import UiPathConversationMessage, UiPathConversationMessageEvent
2425

2526

@@ -28,6 +29,7 @@ class UiPathConversationExchangeStartEvent(BaseModel):
2829

2930
conversation_sequence: int | None = Field(None, alias="conversationSequence")
3031
metadata: dict[str, Any] | None = Field(None, alias="metaData")
32+
timestamp: str | None = None
3133

3234
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
3335

@@ -50,6 +52,7 @@ class UiPathConversationExchangeEvent(BaseModel):
5052
end: UiPathConversationExchangeEndEvent | None = Field(None, alias="endExchange")
5153
message: UiPathConversationMessageEvent | None = None
5254
meta_event: dict[str, Any] | None = Field(None, alias="metaEvent")
55+
error: UiPathConversationErrorEvent | None = Field(None, alias="exchangeError")
5356

5457
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
5558

src/uipath/core/chat/interrupt.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
"""Interrupt events for human-in-the-loop patterns."""
2+
3+
from typing import Any
4+
5+
from pydantic import BaseModel, ConfigDict, Field
6+
7+
8+
class UiPathConversationInterruptStartEvent(BaseModel):
9+
"""Signals the start of an interrupt - a pause point where the agent needs external input."""
10+
11+
type: str
12+
value: Any
13+
14+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
15+
16+
17+
class UiPathConversationInterruptEndEvent(BaseModel):
18+
"""Signals the interrupt end event with the provided value."""
19+
20+
# Can be any type
21+
model_config = ConfigDict(
22+
validate_by_name=True, validate_by_alias=True, extra="allow"
23+
)
24+
25+
26+
class UiPathConversationInterruptEvent(BaseModel):
27+
"""Encapsulates interrupt-related events within a message."""
28+
29+
interrupt_id: str = Field(..., alias="interruptId")
30+
start: UiPathConversationInterruptStartEvent | None = Field(
31+
None, alias="startInterrupt"
32+
)
33+
end: Any | None = Field(None, alias="endInterrupt")
34+
35+
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)

src/uipath/core/chat/message.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
from pydantic import BaseModel, ConfigDict, Field
66

77
from .content import UiPathConversationContentPart, UiPathConversationContentPartEvent
8+
from .error import UiPathConversationErrorEvent
9+
from .interrupt import UiPathConversationInterruptEvent
810
from .tool import UiPathConversationToolCall, UiPathConversationToolCallEvent
911

1012

@@ -39,7 +41,9 @@ class UiPathConversationMessageEvent(BaseModel):
3941
None, alias="contentPart"
4042
)
4143
tool_call: UiPathConversationToolCallEvent | None = Field(None, alias="toolCall")
44+
interrupt: UiPathConversationInterruptEvent | None = None
4245
meta_event: dict[str, Any] | None = Field(None, alias="metaEvent")
46+
error: UiPathConversationErrorEvent | None = Field(None, alias="messageError")
4347

4448
model_config = ConfigDict(validate_by_name=True, validate_by_alias=True)
4549

0 commit comments

Comments
 (0)