Issue
Two webhook helpers in 4.5.0 have type annotations that don't match runtime behavior, forcing adopters to cast or use `.model_construct()`:
1. `extract_webhook_result_data`
Declared return type: `AdcpAsyncResponseData | None`
Actual runtime return: `dict[str, Any]` (callers do `result.get(...)` immediately)
Adopter cast (from salesagent):
```python
result = cast(dict[str, Any] | None, extract_webhook_result_data(payload))
notification_type = result.get("notification_type") if result else None
```
2. `create_mcp_webhook_payload`
Two mismatches:
- `result` parameter: typed narrowly but the function internally calls `hasattr(result, "model_dump")` and accepts any `BaseModel`. The narrow type rejects valid inputs.
- Return type: declared `McpWebhookPayload` but returns `dict[str, Any]` — adopters then do `McpWebhookPayload.model_construct(**result)` to get the typed value back.
Adopter pattern (from salesagent):
```python
mcp_payload_dict = create_mcp_webhook_payload(
task_id=...,
task_type="media_buy_delivery",
result=delivery_response, # type: ignore[arg-type] # accepts any BaseModel via hasattr
status=AdcpTaskStatus.completed,
)
mcp_payload = McpWebhookPayload.model_construct(**mcp_payload_dict)
```
Proposed fix
- `extract_webhook_result_data` → either return the typed model and parse internally, or change the declared return type to `dict[str, Any] | None` and document.
- `create_mcp_webhook_payload` → accept `result: BaseModel | dict[str, Any]`, return `McpWebhookPayload`.
Affected callsites in salesagent
- `src/services/protocol_webhook_service.py:200`
- `src/services/delivery_webhook_scheduler.py:375`
- `src/core/context_manager.py:714`
- `src/admin/blueprints/creatives.py:247`
Filed as part of stale-annotation cleanup work in bokelley/salesagent#208 — the cleanup confirmed every other "library doesn't have it yet" claim was false-positive against 4.5.0; these two are the survivors.
Issue
Two webhook helpers in 4.5.0 have type annotations that don't match runtime behavior, forcing adopters to cast or use `.model_construct()`:
1. `extract_webhook_result_data`
Declared return type: `AdcpAsyncResponseData | None`
Actual runtime return: `dict[str, Any]` (callers do `result.get(...)` immediately)
Adopter cast (from salesagent):
```python
result = cast(dict[str, Any] | None, extract_webhook_result_data(payload))
notification_type = result.get("notification_type") if result else None
```
2. `create_mcp_webhook_payload`
Two mismatches:
Adopter pattern (from salesagent):
```python
mcp_payload_dict = create_mcp_webhook_payload(
task_id=...,
task_type="media_buy_delivery",
result=delivery_response, # type: ignore[arg-type] # accepts any BaseModel via hasattr
status=AdcpTaskStatus.completed,
)
mcp_payload = McpWebhookPayload.model_construct(**mcp_payload_dict)
```
Proposed fix
Affected callsites in salesagent
Filed as part of stale-annotation cleanup work in bokelley/salesagent#208 — the cleanup confirmed every other "library doesn't have it yet" claim was false-positive against 4.5.0; these two are the survivors.