Skip to content

Commit 3c8ccd2

Browse files
Python: Fix merge regressions from main (typing + runtime)
Merging main into the type-checker split branch surfaced regressions that the new five-checker test suite and unit tests caught: Runtime fixes: - anthropic: restore the dropped `cache_read_input_token_count` mapping in _parse_usage_from_anthropic (lost during merge conflict resolution). - gemini: _get_function_calling_mode test helper returned str(enum) ('FunctionCallingConfigMode.AUTO') instead of the enum value ('AUTO'). - openai: _response_id_from_token test helper was an infinite self-recursion; return token['response_id']. - orchestrations: reset output_events per approval iteration so the terminal output assertion counts only the final run. - core: drop a stale duplicate harness test whose message ('non-negative') contradicted the source ('positive'). - purview: import PolicyLocation/PolicyScope/ProtectionScopeActivities/ ExecutionMode used by the processor tests. Type-checker fixes (tests, relaxed profile): - core: pyright/mypy/pyrefly/ty/zuban green-ups across the harness, MCP, observability and types tests. - anthropic/openai: route provider-namespaced UsageDetails keys through a dict cast (extra_items TypedDict unsupported by mypy/ty). - purview: typed model constructors and cache-mock casts. - ag-ui: annotate WorkflowContext[Any, Any] so yield_output accepts test payloads, guard Optional forwarded_props, and ty-ignore intentional bad args. Source pyright (sole source checker) flagged unnecessary ignores newly introduced by merged code in core _tools.py and declarative _declarative_base.py. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 8c67ad0 commit 3c8ccd2

20 files changed

Lines changed: 313 additions & 232 deletions

File tree

python/packages/ag-ui/tests/ag_ui/test_endpoint.py

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"""Tests for FastAPI endpoint creation (_endpoint.py)."""
44

55
import json
6-
from typing import Any
6+
from typing import Any, cast
77

88
import pytest
99
from ag_ui.core import MessagesSnapshotEvent, RunStartedEvent, StateSnapshotEvent
@@ -82,7 +82,7 @@ async def test_add_endpoint_with_workflow_protocol():
8282
"""Test adding endpoint with native Workflow support."""
8383

8484
@executor(id="start")
85-
async def start(message: Any, ctx: WorkflowContext) -> None:
85+
async def start(message: Any, ctx: WorkflowContext[Any, Any]) -> None:
8686
await ctx.yield_output("Workflow response") # type: ignore[arg-type] # pyrefly: ignore[bad-argument-type] # ty: ignore[invalid-argument-type]
8787

8888
app = FastAPI()
@@ -695,7 +695,7 @@ async def stream_fn(messages: Any, options: Any, **kwargs: Any):
695695
path="/snapshots",
696696
state_schema={"tenant": {"type": "string"}},
697697
snapshot_store=store,
698-
snapshot_scope_resolver=lambda request: request.forwarded_props["tenant"],
698+
snapshot_scope_resolver=lambda request: cast("dict[str, Any]", request.forwarded_props)["tenant"],
699699
)
700700
client = TestClient(app)
701701

@@ -994,14 +994,16 @@ async def test_workflow_endpoint_hydrates_emitted_snapshots_without_invoking_wor
994994
call_count = 0
995995

996996
@executor(id="snapshotter")
997-
async def snapshotter(message: Any, ctx: WorkflowContext) -> None:
997+
async def snapshotter(message: Any, ctx: WorkflowContext[Any, Any]) -> None:
998998
nonlocal call_count
999999
del message
10001000
call_count += 1
10011001
await ctx.yield_output(StateSnapshotEvent(snapshot={"active_agent": "flights"}))
10021002
await ctx.yield_output(
10031003
MessagesSnapshotEvent(
1004-
messages=[{"id": "assistant-snapshot", "role": "assistant", "content": "Stored workflow reply"}]
1004+
messages=cast(
1005+
Any, [{"id": "assistant-snapshot", "role": "assistant", "content": "Stored workflow reply"}]
1006+
)
10051007
)
10061008
)
10071009

@@ -1046,7 +1048,7 @@ async def test_workflow_endpoint_hydrates_synthesized_text_and_tool_snapshot():
10461048
call_count = 0
10471049

10481050
@executor(id="responder")
1049-
async def responder(message: Any, ctx: WorkflowContext) -> None:
1051+
async def responder(message: Any, ctx: WorkflowContext[Any, Any]) -> None:
10501052
nonlocal call_count
10511053
del message
10521054
call_count += 1
@@ -1114,7 +1116,7 @@ async def test_workflow_endpoint_hydrates_interrupted_thread_without_invoking_wo
11141116
call_count = 0
11151117

11161118
@executor(id="requester")
1117-
async def requester(message: Any, ctx: WorkflowContext) -> None:
1119+
async def requester(message: Any, ctx: WorkflowContext[Any, Any]) -> None:
11181120
nonlocal call_count
11191121
del message
11201122
call_count += 1
@@ -1167,7 +1169,7 @@ async def test_workflow_endpoint_run_error_does_not_overwrite_previous_snapshot(
11671169
call_count = 0
11681170

11691171
@executor(id="responder")
1170-
async def responder(message: Any, ctx: WorkflowContext) -> None:
1172+
async def responder(message: Any, ctx: WorkflowContext[Any, Any]) -> None:
11711173
nonlocal call_count
11721174
del message
11731175
call_count += 1
@@ -1464,7 +1466,7 @@ async def test_workflow_preserves_history_across_turns():
14641466
call_count = 0
14651467

14661468
@executor(id="responder")
1467-
async def responder(message: Any, ctx: WorkflowContext) -> None:
1469+
async def responder(message: Any, ctx: WorkflowContext[Any, Any]) -> None:
14681470
nonlocal call_count
14691471
del message
14701472
call_count += 1
@@ -1688,7 +1690,7 @@ async def fake_run_workflow_stream(input_data: Any, workflow: Any):
16881690
monkeypatch.setattr(workflow_module, "run_workflow_stream", fake_run_workflow_stream)
16891691

16901692
@executor(id="noop")
1691-
async def noop(message: Any, ctx: WorkflowContext) -> None:
1693+
async def noop(message: Any, ctx: WorkflowContext[Any, Any]) -> None:
16921694
del message, ctx
16931695

16941696
runner = AgentFrameworkWorkflow(
@@ -1759,7 +1761,7 @@ async def test_workflow_endpoint_snapshot_save_failure_does_not_emit_run_error()
17591761
"""A failing snapshot save after RUN_FINISHED must not emit a second terminal RUN_ERROR."""
17601762

17611763
@executor(id="responder")
1762-
async def responder(message: Any, ctx: WorkflowContext) -> None:
1764+
async def responder(message: Any, ctx: WorkflowContext[Any, Any]) -> None:
17631765
del message
17641766
await ctx.yield_output("Workflow reply")
17651767

@@ -1822,7 +1824,7 @@ def test_workflow_factory_cache_is_scoped_by_snapshot_scope():
18221824
"""The same thread id under different Snapshot Scopes must not share a workflow instance."""
18231825

18241826
@executor(id="noop")
1825-
async def noop(message: Any, ctx: WorkflowContext) -> None:
1827+
async def noop(message: Any, ctx: WorkflowContext[Any, Any]) -> None:
18261828
del message, ctx
18271829

18281830
def factory(thread_id: str) -> Any:

python/packages/ag-ui/tests/ag_ui/test_snapshots.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,10 @@ async def test_in_memory_snapshot_store_rejects_invalid_keys() -> None:
151151
with pytest.raises(ValueError):
152152
await store.save(scope="tenant-a", thread_id="", snapshot=snapshot)
153153
with pytest.raises(TypeError):
154-
await store.save(scope=123, thread_id="thread-1", snapshot=snapshot) # type: ignore[arg-type]
154+
await store.save(scope=123, thread_id="thread-1", snapshot=snapshot) # type: ignore[arg-type] # ty: ignore[invalid-argument-type]
155155
with pytest.raises(ValueError):
156156
await store.get(scope="tenant-a", thread_id="")
157157
with pytest.raises(TypeError):
158-
await store.delete(scope=None, thread_id="thread-1") # type: ignore[arg-type]
158+
await store.delete(scope=None, thread_id="thread-1") # type: ignore[arg-type] # ty: ignore[invalid-argument-type]
159159
with pytest.raises(ValueError):
160160
await store.clear(scope="")

python/packages/anthropic/agent_framework_anthropic/_chat_client.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,6 +1027,7 @@ def _parse_usage_from_anthropic(self, usage: BetaUsage | BetaMessageDeltaUsage |
10271027
usage_details["cache_creation_input_token_count"] = usage.cache_creation_input_tokens
10281028
if usage.cache_read_input_tokens is not None:
10291029
usage_details["anthropic.cache_read_input_tokens"] = usage.cache_read_input_tokens
1030+
usage_details["cache_read_input_token_count"] = usage.cache_read_input_tokens
10301031
return usage_details
10311032

10321033
def _parse_contents_from_anthropic(

python/packages/anthropic/tests/test_anthropic_client.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2350,10 +2350,11 @@ def test_parse_usage_with_cache_tokens(mock_anthropic_client: MagicMock) -> None
23502350
result = client._parse_usage_from_anthropic(mock_usage)
23512351

23522352
assert result is not None
2353+
result_dict = cast("dict[str, Any]", result)
23532354
assert result["output_token_count"] == 50
23542355
assert result["input_token_count"] == 100
2355-
assert result["anthropic.cache_creation_input_tokens"] == 20
2356-
assert result["anthropic.cache_read_input_tokens"] == 30
2356+
assert result_dict["anthropic.cache_creation_input_tokens"] == 20
2357+
assert result_dict["anthropic.cache_read_input_tokens"] == 30
23572358
assert result["cache_creation_input_token_count"] == 20
23582359
assert result["cache_read_input_token_count"] == 30
23592360

@@ -2371,9 +2372,10 @@ def test_parse_usage_preserves_zero_cache_tokens(mock_anthropic_client: MagicMoc
23712372
result = client._parse_usage_from_anthropic(mock_usage)
23722373

23732374
assert result is not None
2374-
assert result["anthropic.cache_creation_input_tokens"] == 0
2375+
result_dict = cast("dict[str, Any]", result)
2376+
assert result_dict["anthropic.cache_creation_input_tokens"] == 0
23752377
assert result["cache_creation_input_token_count"] == 0
2376-
assert result["anthropic.cache_read_input_tokens"] == 0
2378+
assert result_dict["anthropic.cache_read_input_tokens"] == 0
23772379
assert result["cache_read_input_token_count"] == 0
23782380

23792381

python/packages/core/agent_framework/_tools.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1730,7 +1730,7 @@ async def _try_execute_function_calls(
17301730
id=fcc.call_id, # type: ignore[arg-type]
17311731
function_call=fcc,
17321732
)
1733-
tool_name = fcc.name # type: ignore[attr-defined]
1733+
tool_name = fcc.name
17341734
if tool_name is None:
17351735
visible_requests.append(approval_request)
17361736
continue

python/packages/core/tests/core/test_feature_stage.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ class HelperReleaseCandidateFeature(str, Enum):
4646

4747

4848
@pytest.fixture(autouse=True)
49-
def clear_feature_warning_state() -> Generator[None]: # type: ignore[misc] # pyrefly: ignore[bad-return] # ty: ignore[invalid-return-type]
49+
def clear_feature_warning_state() -> Generator[None]: # type: ignore[misc] # pyrefly: ignore[bad-return]
5050
_WARNED_FEATURES.clear()
5151
yield
5252
_WARNED_FEATURES.clear()

python/packages/core/tests/core/test_function_invocation_logic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -635,11 +635,11 @@ def func_with_approval(arg1: str) -> str:
635635

636636
messages: list[Any]
637637
if not streaming:
638-
response = await chat_client_base.get_response([Message(role="user", contents=["hello"])], options=options) # type: ignore[call-overload] # pyrefly: ignore[no-matching-overload] # ty: ignore[no-matching-overload]
638+
response = await chat_client_base.get_response([Message(role="user", contents=["hello"])], options=options) # type: ignore[call-overload] # pyrefly: ignore[no-matching-overload]
639639
messages = response.messages
640640
else:
641641
updates = []
642-
async for update in chat_client_base.get_response( # type: ignore[call-overload] # pyrefly: ignore[no-matching-overload] # ty: ignore[no-matching-overload]
642+
async for update in chat_client_base.get_response( # type: ignore[call-overload] # pyrefly: ignore[no-matching-overload]
643643
[Message(role="user", contents=["hello"])], options=options, stream=True
644644
):
645645
updates.append(update)

0 commit comments

Comments
 (0)