From 5ea14462d3be89859a0bf57802f24100f7d78f9b Mon Sep 17 00:00:00 2001 From: Jiwon Kim Date: Mon, 18 May 2026 21:20:40 -0700 Subject: [PATCH 1/2] Fix agents sdk compatibility --- chatkit/agents.py | 33 +++++++++++++++++++++++---------- pyproject.toml | 2 +- tests/test_agents.py | 44 ++++++++++++++++++++++++++++++++++++++++++++ uv.lock | 2 +- 4 files changed, 69 insertions(+), 12 deletions(-) diff --git a/chatkit/agents.py b/chatkit/agents.py index c061846..7f435e3 100644 --- a/chatkit/agents.py +++ b/chatkit/agents.py @@ -23,6 +23,7 @@ ) from openai.types.responses import ( EasyInputMessageParam, + ResponseFunctionToolCall, ResponseFunctionToolCallParam, ResponseInputContentParam, ResponseInputImageParam, @@ -455,6 +456,24 @@ async def _convert_annotation( return None +def _function_call_metadata(raw_item: object) -> tuple[str | None, str | None]: + if isinstance(raw_item, dict): + if raw_item.get("type") != "function_call": + return None, None + + call_id = raw_item.get("call_id") + item_id = raw_item.get("id") + return ( + call_id if isinstance(call_id, str) else None, + item_id if isinstance(item_id, str) else None, + ) + + if isinstance(raw_item, ResponseFunctionToolCall): + return raw_item.call_id, raw_item.id + + return None, None + + async def stream_agent_response( context: AgentContext, result: RunResultStreaming, @@ -554,16 +573,10 @@ def end_workflow(item: WorkflowItem): if event.type == "run_item_stream_event": event = event.item if event.type == "tool_call_item": - raw_item = event.raw_item - if isinstance(raw_item, dict): - if raw_item.get("type") == "function_call": - current_tool_call = event.call_id - current_item_id = raw_item.get("id") - assert current_item_id - produced_items.add(current_item_id) - elif raw_item.type == "function_call": - current_tool_call = event.call_id - current_item_id = raw_item.id + current_tool_call, current_item_id = _function_call_metadata( + event.raw_item + ) + if current_tool_call: assert current_item_id produced_items.add(current_item_id) continue diff --git a/pyproject.toml b/pyproject.toml index 9f24fee..e9ec048 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openai-chatkit" -version = "1.6.4" +version = "1.6.5" description = "A ChatKit backend SDK." readme = "README.md" requires-python = ">=3.10" diff --git a/tests/test_agents.py b/tests/test_agents.py index 5a97d07..1611162 100644 --- a/tests/test_agents.py +++ b/tests/test_agents.py @@ -27,6 +27,7 @@ from openai.types.responses import ( EasyInputMessageParam, ResponseFileSearchToolCall, + ResponseFunctionToolCall, ResponseInputContentParam, ResponseInputTextParam, ResponseOutputItemAddedEvent, @@ -59,6 +60,7 @@ from chatkit.agents import ( AgentContext, + ClientToolCall, ResponseStreamConverter, ThreadItemConverter, accumulate_text, @@ -311,6 +313,48 @@ async def widget_generator(): ) +async def test_client_tool_call_uses_raw_function_call_id(): + context = AgentContext( + previous_response_id=None, + thread=thread, + store=mock_store, + request_context=None, + client_tool_call=ClientToolCall(name="get_selection", arguments={}), + ) + result = make_result() + raw_item = ResponseFunctionToolCall( + id="fc_123", + type="function_call", + call_id="call_123", + name="get_selection", + arguments="{}", + status="completed", + ) + result.add_event( + RunItemStreamEvent( + name="tool_called", + item=ToolCallItem( + agent=Agent("Assistant"), + raw_item=raw_item, + ), + ) + ) + result.done() + + events = await all_events( + stream_agent_response( + context=context, + result=result, + ) + ) + + assert len(events) == 1 + assert isinstance(events[0], ThreadItemDoneEvent) + assert isinstance(events[0].item, ClientToolCallItem) + assert events[0].item.id == "fc_123" + assert events[0].item.call_id == "call_123" + + async def test_accumulate_text(): def delta(text: str) -> RawResponsesStreamEvent: return RawResponsesStreamEvent( diff --git a/uv.lock b/uv.lock index cba19bc..e4ad205 100644 --- a/uv.lock +++ b/uv.lock @@ -1155,7 +1155,7 @@ wheels = [ [[package]] name = "openai-chatkit" -version = "1.6.4" +version = "1.6.5" source = { virtual = "." } dependencies = [ { name = "jinja2" }, From 44f5190b0b19afea9618e0fc295c5975f1fe4b7c Mon Sep 17 00:00:00 2001 From: Jiwon Kim Date: Mon, 18 May 2026 21:46:28 -0700 Subject: [PATCH 2/2] Fix makefile and uv.lock --- Makefile | 34 ++++++++++++++++++++-------------- uv.lock | 3 --- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 35b073d..993e749 100644 --- a/Makefile +++ b/Makefile @@ -1,34 +1,40 @@ -.PHONY: sync format format-check lint mypy pyright tests gen-docs build-docs serve-docs deploy-docs check +.PHONY: sync install format format-check lint mypy pyright test build serve-docs deploy-docs check -install: - uv sync --all-extras --all-packages --group dev +UV_ENV := env -i PATH="$(PATH)" HOME="$(HOME)" +UV := $(UV_ENV) uv --no-config +UV_LOCK_ARGS := --locked --default-index https://pypi.org/simple + +sync: + $(UV) sync $(UV_LOCK_ARGS) --all-extras --all-packages --group dev + +install: sync format: - uv run ruff format - uv run ruff check --fix + $(UV) run $(UV_LOCK_ARGS) ruff format + $(UV) run $(UV_LOCK_ARGS) ruff check --fix format-check: - uv run ruff format --check + $(UV) run $(UV_LOCK_ARGS) ruff format --check lint: - uv run ruff check + $(UV) run $(UV_LOCK_ARGS) ruff check mypy: - uv run mypy . + $(UV) run $(UV_LOCK_ARGS) mypy . pyright: - uv run pyright + $(UV) run $(UV_LOCK_ARGS) pyright test: - PYTHONPATH=. uv run pytest + $(UV_ENV) PYTHONPATH=. uv --no-config run $(UV_LOCK_ARGS) pytest build: - uv build + $(UV) build --default-index https://pypi.org/simple serve-docs: - uv run mkdocs serve + $(UV) run $(UV_LOCK_ARGS) mkdocs serve deploy-docs: - uv run mkdocs gh-deploy --force --verbose + $(UV) run $(UV_LOCK_ARGS) mkdocs gh-deploy --force --verbose -check: format-check lint pyright test \ No newline at end of file +check: format-check lint pyright test diff --git a/uv.lock b/uv.lock index e4ad205..cdd294c 100644 --- a/uv.lock +++ b/uv.lock @@ -6,9 +6,6 @@ resolution-markers = [ "python_full_version < '3.15'", ] -[options] -exclude-newer = "2026-05-06T15:30:24Z" - [[package]] name = "annotated-doc" version = "0.0.4"