From 7861b9a0d7add299fbb13ba719be38570da84a76 Mon Sep 17 00:00:00 2001 From: Jiwon Kim Date: Thu, 20 Nov 2025 15:44:59 -0800 Subject: [PATCH 1/2] ThreadItemUpdated is now an alias for ThreadItemUpdatedEvent --- chatkit/types.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/chatkit/types.py b/chatkit/types.py index 1c34b9f..eb7b7f3 100644 --- a/chatkit/types.py +++ b/chatkit/types.py @@ -284,7 +284,7 @@ class ThreadItemAddedEvent(BaseModel): item: ThreadItem -class ThreadItemUpdated(BaseModel): +class ThreadItemUpdatedEvent(BaseModel): """Event describing an update to an existing thread item.""" type: Literal["thread.item.updated"] = "thread.item.updated" @@ -292,6 +292,10 @@ class ThreadItemUpdated(BaseModel): update: ThreadItemUpdate +# Type alias for backwards compatibility +ThreadItemUpdated = ThreadItemUpdatedEvent + + class ThreadItemDoneEvent(BaseModel): """Event emitted when a thread item is marked complete.""" From 643a02f71cc6dd0a2513fe1aa9cb160e5afe2f70 Mon Sep 17 00:00:00 2001 From: Jiwon Kim Date: Fri, 21 Nov 2025 12:57:04 -0800 Subject: [PATCH 2/2] update references to ThreadItemUpdated -> ThreadItemUpdatedEvent --- chatkit/agents.py | 20 +++++++++---------- chatkit/server.py | 4 ++-- tests/test_agents.py | 38 ++++++++++++++++++------------------ tests/test_chatkit_server.py | 14 ++++++------- 4 files changed, 38 insertions(+), 38 deletions(-) diff --git a/chatkit/agents.py b/chatkit/agents.py index 6fdff22..9f6d48e 100644 --- a/chatkit/agents.py +++ b/chatkit/agents.py @@ -63,7 +63,7 @@ ThreadItemAddedEvent, ThreadItemDoneEvent, ThreadItemRemovedEvent, - ThreadItemUpdated, + ThreadItemUpdatedEvent, ThreadMetadata, ThreadStreamEvent, URLSource, @@ -168,7 +168,7 @@ async def update_workflow_task(self, task: Task, task_index: int) -> None: # ensure reference is updated in case task is a copy self.workflow_item.workflow.tasks[task_index] = task await self.stream( - ThreadItemUpdated( + ThreadItemUpdatedEvent( item_id=self.workflow_item.id, update=WorkflowTaskUpdated( task=task, @@ -191,7 +191,7 @@ async def add_workflow_task(self, task: Task) -> None: await self.stream(ThreadItemAddedEvent(item=self.workflow_item)) else: await self.stream( - ThreadItemUpdated( + ThreadItemUpdatedEvent( item_id=self.workflow_item.id, update=WorkflowTaskAdded( task=task, @@ -448,7 +448,7 @@ def end_workflow(item: WorkflowItem): if event.part.type == "reasoning_text": continue content = _convert_content(event.part) - yield ThreadItemUpdated( + yield ThreadItemUpdatedEvent( item_id=event.item_id, update=AssistantMessageContentPartAdded( content_index=event.content_index, @@ -456,7 +456,7 @@ def end_workflow(item: WorkflowItem): ), ) elif event.type == "response.output_text.delta": - yield ThreadItemUpdated( + yield ThreadItemUpdatedEvent( item_id=event.item_id, update=AssistantMessageContentPartTextDelta( content_index=event.content_index, @@ -464,7 +464,7 @@ def end_workflow(item: WorkflowItem): ), ) elif event.type == "response.output_text.done": - yield ThreadItemUpdated( + yield ThreadItemUpdatedEvent( item_id=event.item_id, update=AssistantMessageContentPartDone( content_index=event.content_index, @@ -485,7 +485,7 @@ def end_workflow(item: WorkflowItem): item_annotation_count[event.item_id][event.content_index] = ( annotation_index + 1 ) - yield ThreadItemUpdated( + yield ThreadItemUpdatedEvent( item_id=event.item_id, update=AssistantMessageContentPartAnnotationAdded( content_index=event.content_index, @@ -533,7 +533,7 @@ def end_workflow(item: WorkflowItem): task=ThoughtTask(content=event.delta), ) ctx.workflow_item.workflow.tasks.append(streaming_thought.task) - yield ThreadItemUpdated( + yield ThreadItemUpdatedEvent( item_id=ctx.workflow_item.id, update=WorkflowTaskAdded( task=streaming_thought.task, @@ -547,7 +547,7 @@ def end_workflow(item: WorkflowItem): and event.summary_index == streaming_thought.index ): streaming_thought.task.content += event.delta - yield ThreadItemUpdated( + yield ThreadItemUpdatedEvent( item_id=ctx.workflow_item.id, update=WorkflowTaskUpdated( task=streaming_thought.task, @@ -578,7 +578,7 @@ def end_workflow(item: WorkflowItem): task=task, task_index=ctx.workflow_item.workflow.tasks.index(task), ) - yield ThreadItemUpdated( + yield ThreadItemUpdatedEvent( item_id=ctx.workflow_item.id, update=update, ) diff --git a/chatkit/server.py b/chatkit/server.py index c9a432f..66d7b58 100644 --- a/chatkit/server.py +++ b/chatkit/server.py @@ -47,7 +47,7 @@ ThreadItemDoneEvent, ThreadItemRemovedEvent, ThreadItemReplacedEvent, - ThreadItemUpdated, + ThreadItemUpdatedEvent, ThreadMetadata, ThreadsAddClientToolOutputReq, ThreadsAddUserMessageReq, @@ -209,7 +209,7 @@ async def stream_widget( try: new_state = await widget.__anext__() for update in diff_widget(last_state, new_state): - yield ThreadItemUpdated( + yield ThreadItemUpdatedEvent( item_id=item_id, update=update, ) diff --git a/tests/test_agents.py b/tests/test_agents.py index 8185651..045b90e 100644 --- a/tests/test_agents.py +++ b/tests/test_agents.py @@ -86,7 +86,7 @@ Thread, ThreadItemAddedEvent, ThreadItemDoneEvent, - ThreadItemUpdated, + ThreadItemUpdatedEvent, ThreadStreamEvent, URLSource, UserMessageItem, @@ -231,7 +231,7 @@ async def widget_generator(): assert isinstance(events[0].item, WidgetItem) assert events[0].item.widget == Card(children=[Text(id="text", value="")]) - assert isinstance(events[1], ThreadItemUpdated) + assert isinstance(events[1], ThreadItemUpdatedEvent) assert events[1].update.type == "widget.streaming_text.value_delta" assert events[1].update.component_id == "text" assert events[1].update.delta == "Hello, world" @@ -271,7 +271,7 @@ async def widget_generator(): assert isinstance(events[0].item, WidgetItem) assert events[0].item.widget == Card(children=[Text(id="text", value="Hello!")]) - assert isinstance(events[1], ThreadItemUpdated) + assert isinstance(events[1], ThreadItemUpdatedEvent) assert events[1].update.type == "widget.root.updated" assert events[1].update.widget == Card( children=[Text(key="other text", value="World!", streaming=False)] @@ -788,7 +788,7 @@ async def test_stream_agent_response_maps_events(): sequence_number=0, ), ), - ThreadItemUpdated( + ThreadItemUpdatedEvent( item_id="123", update=AssistantMessageContentPartTextDelta( content_index=0, @@ -812,7 +812,7 @@ async def test_stream_agent_response_maps_events(): sequence_number=1, ), ), - ThreadItemUpdated( + ThreadItemUpdatedEvent( item_id="123", update=AssistantMessageContentPartAdded( content_index=1, @@ -833,7 +833,7 @@ async def test_stream_agent_response_maps_events(): sequence_number=2, ), ), - ThreadItemUpdated( + ThreadItemUpdatedEvent( item_id="123", update=AssistantMessageContentPartDone( content_index=0, @@ -862,7 +862,7 @@ async def test_stream_agent_response_maps_events(): sequence_number=3, ), ), - ThreadItemUpdated( + ThreadItemUpdatedEvent( item_id="123", update=AssistantMessageContentPartAnnotationAdded( content_index=0, @@ -949,7 +949,7 @@ def add_annotation_event(annotation, sequence_number): events = await all_events(stream_agent_response(context, result)) assert events == [ - ThreadItemUpdated( + ThreadItemUpdatedEvent( item_id=item_id, update=AssistantMessageContentPartAnnotationAdded( content_index=0, @@ -960,7 +960,7 @@ def add_annotation_event(annotation, sequence_number): ), ), ), - ThreadItemUpdated( + ThreadItemUpdatedEvent( item_id=item_id, update=AssistantMessageContentPartAnnotationAdded( content_index=0, @@ -1297,8 +1297,8 @@ async def test_workflow_streams_first_thought(): event = await anext(stream) assert context.workflow_item is not None assert len(context.workflow_item.workflow.tasks) == 1 - assert isinstance(event, ThreadItemUpdated) - assert event == ThreadItemUpdated( + assert isinstance(event, ThreadItemUpdatedEvent) + assert event == ThreadItemUpdatedEvent( item_id=context.workflow_item.id, update=WorkflowTaskAdded( task=ThoughtTask(content="Think"), @@ -1310,8 +1310,8 @@ async def test_workflow_streams_first_thought(): event = await anext(stream) assert context.workflow_item is not None assert len(context.workflow_item.workflow.tasks) == 1 - assert isinstance(event, ThreadItemUpdated) - assert event == ThreadItemUpdated( + assert isinstance(event, ThreadItemUpdatedEvent) + assert event == ThreadItemUpdatedEvent( item_id=context.workflow_item.id, update=WorkflowTaskUpdated( task=ThoughtTask(content="Thinking 1"), @@ -1323,8 +1323,8 @@ async def test_workflow_streams_first_thought(): event = await anext(stream) assert context.workflow_item is not None assert len(context.workflow_item.workflow.tasks) == 1 - assert isinstance(event, ThreadItemUpdated) - assert event == ThreadItemUpdated( + assert isinstance(event, ThreadItemUpdatedEvent) + assert event == ThreadItemUpdatedEvent( item_id=context.workflow_item.id, update=WorkflowTaskUpdated( task=ThoughtTask(content="Thinking 1"), @@ -1336,8 +1336,8 @@ async def test_workflow_streams_first_thought(): event = await anext(stream) assert context.workflow_item is not None assert len(context.workflow_item.workflow.tasks) == 2 - assert isinstance(event, ThreadItemUpdated) - assert event == ThreadItemUpdated( + assert isinstance(event, ThreadItemUpdatedEvent) + assert event == ThreadItemUpdatedEvent( item_id=context.workflow_item.id, update=WorkflowTaskAdded( task=ThoughtTask(content="Thinking 2"), @@ -1420,8 +1420,8 @@ async def test_workflow_ends_on_message(): event = await anext(stream) assert context.workflow_item is not None assert len(context.workflow_item.workflow.tasks) == 1 - assert isinstance(event, ThreadItemUpdated) - assert event == ThreadItemUpdated( + assert isinstance(event, ThreadItemUpdatedEvent) + assert event == ThreadItemUpdatedEvent( item_id=context.workflow_item.id, update=WorkflowTaskAdded( task=ThoughtTask(content="Thinking 1"), diff --git a/tests/test_chatkit_server.py b/tests/test_chatkit_server.py index 44748ef..3526532 100644 --- a/tests/test_chatkit_server.py +++ b/tests/test_chatkit_server.py @@ -49,7 +49,7 @@ ThreadItemDoneEvent, ThreadItemRemovedEvent, ThreadItemReplacedEvent, - ThreadItemUpdated, + ThreadItemUpdatedEvent, ThreadListParams, ThreadMetadata, ThreadRetryAfterItemParams, @@ -756,7 +756,7 @@ async def action( actions.append((action, sender)) assert sender - yield ThreadItemUpdated( + yield ThreadItemUpdatedEvent( item_id=sender.id, update=WidgetRootUpdated( widget=Card( @@ -807,7 +807,7 @@ async def action( assert len(events) == 1 assert events[0].type == "thread.item.updated" - assert isinstance(events[0], ThreadItemUpdated) + assert isinstance(events[0], ThreadItemUpdatedEvent) assert events[0].update.type == "widget.root.updated" assert events[0].update.widget == Card(children=[Text(value="Email sent!")]) @@ -1090,17 +1090,17 @@ async def widget_generator(): assert isinstance(events[0].item, WidgetItem) assert events[0].item.widget == Card(children=[Text(id="text", value="")]) - assert isinstance(events[1], ThreadItemUpdated) + assert isinstance(events[1], ThreadItemUpdatedEvent) assert events[1].update.type == "widget.streaming_text.value_delta" assert events[1].update.component_id == "text" assert events[1].update.delta == "Hel" - assert isinstance(events[2], ThreadItemUpdated) + assert isinstance(events[2], ThreadItemUpdatedEvent) assert events[2].update.type == "widget.streaming_text.value_delta" assert events[2].update.component_id == "text" assert events[2].update.delta == "lo," - assert isinstance(events[3], ThreadItemUpdated) + assert isinstance(events[3], ThreadItemUpdatedEvent) assert events[3].update.type == "widget.streaming_text.value_delta" assert events[3].update.component_id == "text" assert events[3].update.delta == " world" @@ -1128,7 +1128,7 @@ async def widget_generator(): assert isinstance(events[0].item, WidgetItem) assert events[0].item.widget == Card(children=[Text(id="text", value="Hello")]) - assert isinstance(events[1], ThreadItemUpdated) + assert isinstance(events[1], ThreadItemUpdatedEvent) assert events[1].update.type == "widget.root.updated" assert events[1].update.widget == Card(children=[Text(id="text", value="World")])