molecule-core/workspace/tests/test_delegation.py
Hongming Wang 5071454074 fix(delegation): lazy-refresh QUEUED state from platform; live DELEGATION_* events
Critical follow-up to PR #2126's review. Two real bugs:

1. **Runtime QUEUED never resolved.** Platform's drain stitch updates
   the platform's delegate_result row when a queued delegation finally
   completes, but never pushes back to the runtime. The LLM polling
   check_delegation_status saw status="queued" forever — combined with
   the new docstring guidance ("queued → wait, peer will reply"), the
   model would wait indefinitely on a state that never resolves.
   Strictly worse than pre-PR behavior where it would have at least
   bypassed.

2. **Live updates dead code.** delegation.go writes activity rows by
   direct INSERT INTO activity_logs, bypassing the LogActivity helper
   that fires ACTIVITY_LOGGED. Adding "delegation" to the canvas's
   ACTIVITY_LOGGED filter (PR #2126 first cut) was inert — initial
   GET worked, live updates did not.

Fix:

(1) Runtime side, workspace/builtin_tools/delegation.py:
  - New `_refresh_queued_from_platform(task_id)` async helper that
    pulls /workspaces/<self>/delegations and finds the platform-side
    delegate_result row for our task_id.
  - check_delegation_status calls _refresh when local status is
    QUEUED, so the LLM's poll itself drives state convergence.
  - Best-effort: GET failure leaves local state untouched, next
    poll retries.
  - Docstring updated to reflect the actual behavior ("polls
    transparently — keep polling and you'll see the flip").
  - 4 new tests cover: QUEUED → completed via refresh; QUEUED →
    failed via refresh; refresh keeps QUEUED when platform hasn't
    resolved; refresh swallows network errors safely.

(2) Canvas side, AgentCommsPanel.tsx WS push handler:
  - Listens for DELEGATION_SENT / DELEGATION_STATUS / DELEGATION_COMPLETE
    / DELEGATION_FAILED in addition to ACTIVITY_LOGGED.
  - Each event's payload synthesized into an ActivityEntry shape
    so toCommMessage's existing delegation branch maps it. Status
    derived: STATUS uses payload.status, COMPLETE → "completed",
    FAILED → "failed", SENT → "pending".
  - The ACTIVITY_LOGGED branch keeps the "delegation" type accepted
    as a no-op-today / future-proof path: if delegation handlers
    are ever refactored to call LogActivity, this lights up
    automatically without another canvas change.

Doesn't change: the docstring guidance ("queued → wait, don't bypass")
is now actually load-bearing because the refresh path will deliver
the eventual outcome. Without the refresh, the guidance was a trap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 16:05:04 -07:00

661 lines
24 KiB
Python

"""Tests for tools/delegation.py (async delegation model).
The delegation tool now returns immediately with a task_id and runs the
A2A request in the background. Tests verify:
1. Immediate return with task_id
2. Background task completion
3. check_delegation_status retrieval
4. Error handling (RBAC, discovery, network)
"""
import asyncio
import importlib.util
import os
import sys
from unittest.mock import AsyncMock, MagicMock, patch
import httpx
import pytest
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _make_mock_client(
discover_status=200,
discover_payload=None,
discover_exc=None,
a2a_status=200,
a2a_payload=None,
):
"""Return (mock_client, mock_client_class) for patching httpx.AsyncClient."""
if discover_payload is None:
discover_payload = {"url": "http://peer:8000"}
if a2a_payload is None:
a2a_payload = {
"result": {
"parts": [{"kind": "text", "text": "done"}],
"artifacts": [],
}
}
mock_resp_discover = MagicMock()
mock_resp_discover.status_code = discover_status
mock_resp_discover.json.return_value = discover_payload
mock_resp_a2a = MagicMock()
mock_resp_a2a.status_code = a2a_status
mock_resp_a2a.json.return_value = a2a_payload
mock_client = AsyncMock()
if discover_exc:
mock_client.get = AsyncMock(side_effect=discover_exc)
else:
mock_client.get = AsyncMock(return_value=mock_resp_discover)
mock_client.post = AsyncMock(return_value=mock_resp_a2a)
mock_cls = MagicMock()
mock_cls.return_value.__aenter__ = AsyncMock(return_value=mock_client)
mock_cls.return_value.__aexit__ = AsyncMock(return_value=False)
return mock_client, mock_cls
@pytest.fixture
def delegation_mocks(monkeypatch):
"""Load the real delegation module with mocked dependencies."""
mock_audit = MagicMock()
mock_audit.check_permission = MagicMock(return_value=True)
mock_audit.get_workspace_roles = MagicMock(return_value=(["operator"], {}))
mock_audit.log_event = MagicMock()
mock_span = MagicMock()
mock_span.set_attribute = MagicMock()
mock_span.record_exception = MagicMock()
mock_span.__enter__ = MagicMock(return_value=mock_span)
mock_span.__exit__ = MagicMock(return_value=False)
mock_tracer = MagicMock()
mock_tracer.start_as_current_span = MagicMock(return_value=mock_span)
mock_telemetry = MagicMock()
mock_telemetry.get_tracer = MagicMock(return_value=mock_tracer)
mock_telemetry.inject_trace_headers = MagicMock(side_effect=lambda h: h)
mock_telemetry.get_current_traceparent = MagicMock(return_value="")
for attr in ["A2A_SOURCE_WORKSPACE", "A2A_TARGET_WORKSPACE", "A2A_TASK_ID", "WORKSPACE_ID_ATTR"]:
setattr(mock_telemetry, attr, attr)
monkeypatch.setitem(sys.modules, "builtin_tools.audit", mock_audit)
monkeypatch.setitem(sys.modules, "builtin_tools.telemetry", mock_telemetry)
monkeypatch.setenv("WORKSPACE_ID", "ws-self")
monkeypatch.setenv("PLATFORM_URL", "http://test:8080")
spec = importlib.util.spec_from_file_location(
"builtin_tools.delegation",
os.path.join(os.path.dirname(__file__), "..", "builtin_tools", "delegation.py"),
)
mod = importlib.util.module_from_spec(spec)
monkeypatch.setitem(sys.modules, "builtin_tools.delegation", mod)
spec.loader.exec_module(mod)
mod.DELEGATION_RETRY_ATTEMPTS = 2
mod.DELEGATION_RETRY_DELAY = 0.0
# Clear state between tests
mod._delegations.clear()
mod._background_tasks.clear()
return mod, mock_audit, mock_telemetry, mock_span
async def _invoke(mod, workspace_id="target", task="do stuff"):
"""Call delegate_to_workspace and return the immediate result."""
fn = mod.delegate_to_workspace
if hasattr(fn, "ainvoke"):
return await fn.ainvoke({"workspace_id": workspace_id, "task": task})
return await fn(workspace_id=workspace_id, task=task)
async def _invoke_and_wait(mod, workspace_id="target", task="do stuff"):
"""Call delegate_to_workspace, wait for background task, return status."""
result = await _invoke(mod, workspace_id, task)
# Wait for all background tasks to complete
if mod._background_tasks:
await asyncio.gather(*mod._background_tasks, return_exceptions=True)
# Get final status
if "task_id" in result:
fn = mod.check_delegation_status
if hasattr(fn, "ainvoke"):
return await fn.ainvoke({"task_id": result["task_id"]})
return await fn(task_id=result["task_id"])
return result
# ---------------------------------------------------------------------------
# Tests
# ---------------------------------------------------------------------------
class TestRBAC:
@pytest.mark.asyncio
async def test_rbac_deny(self, delegation_mocks):
mod, mock_audit, *_ = delegation_mocks
mock_audit.check_permission.return_value = False
result = await _invoke(mod)
assert result["success"] is False
assert "RBAC" in result["error"]
class TestAsyncDelegation:
@pytest.mark.asyncio
async def test_returns_immediately_with_task_id(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client()
with patch("httpx.AsyncClient", mock_cls):
result = await _invoke(mod)
assert result["success"] is True
assert "task_id" in result
assert result["status"] == "delegated"
@pytest.mark.asyncio
async def test_background_task_completes(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client()
with patch("httpx.AsyncClient", mock_cls):
status = await _invoke_and_wait(mod)
assert status["status"] == "completed"
assert "done" in status["result"]
@pytest.mark.asyncio
async def test_check_delegation_list_all(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client()
with patch("httpx.AsyncClient", mock_cls):
await _invoke(mod, workspace_id="ws-a", task="task A")
await _invoke(mod, workspace_id="ws-b", task="task B")
fn = mod.check_delegation_status
if hasattr(fn, "ainvoke"):
result = await fn.ainvoke({"task_id": ""})
else:
result = await fn(task_id="")
assert result["count"] == 2
@pytest.mark.asyncio
async def test_check_delegation_not_found(self, delegation_mocks):
mod, *_ = delegation_mocks
fn = mod.check_delegation_status
if hasattr(fn, "ainvoke"):
result = await fn.ainvoke({"task_id": "nonexistent"})
else:
result = await fn(task_id="nonexistent")
assert "error" in result
class TestDiscovery:
@pytest.mark.asyncio
async def test_discovery_403(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client(discover_status=403)
with patch("httpx.AsyncClient", mock_cls):
status = await _invoke_and_wait(mod)
assert status["status"] == "failed"
assert "Discovery failed" in status.get("error", "")
@pytest.mark.asyncio
async def test_discovery_404(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client(discover_status=404)
with patch("httpx.AsyncClient", mock_cls):
status = await _invoke_and_wait(mod)
assert status["status"] == "failed"
@pytest.mark.asyncio
async def test_discovery_no_url(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client(discover_payload={"url": ""})
with patch("httpx.AsyncClient", mock_cls):
status = await _invoke_and_wait(mod)
assert status["status"] == "failed"
assert "No URL" in status.get("error", "")
@pytest.mark.asyncio
async def test_discovery_exception(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client(discover_exc=Exception("dns fail"))
with patch("httpx.AsyncClient", mock_cls):
status = await _invoke_and_wait(mod)
assert status["status"] == "failed"
assert "dns fail" in status.get("error", "")
class TestA2ASuccess:
@pytest.mark.asyncio
async def test_success_with_parts(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client(
a2a_payload={"result": {"parts": [{"kind": "text", "text": "hello world"}]}}
)
with patch("httpx.AsyncClient", mock_cls):
status = await _invoke_and_wait(mod)
assert status["status"] == "completed"
assert "hello world" in status["result"]
@pytest.mark.asyncio
async def test_success_with_artifacts(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client(
a2a_payload={
"result": {
"artifacts": [{"parts": [{"kind": "text", "text": "artifact text"}]}],
"parts": [],
}
}
)
with patch("httpx.AsyncClient", mock_cls):
status = await _invoke_and_wait(mod)
assert status["status"] == "completed"
assert "artifact text" in status["result"]
class TestA2AQueued:
"""HTTP 202 + {queued: true} comes back when the peer's a2a-proxy
accepted the request but the peer is mid-task. Pre-fix the runtime
treated this as 'no 200 → fall through to FAILED', which led the
LLM to conclude the peer was permanently unavailable and bypass
delegation entirely. Post-fix the status is QUEUED and the LLM
sees explicit guidance to wait."""
@pytest.mark.asyncio
async def test_queued_marks_status_queued_not_failed(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client(
a2a_status=202,
a2a_payload={"queued": True, "summary": "Delegation queued — target at capacity"},
)
with patch("httpx.AsyncClient", mock_cls):
status = await _invoke_and_wait(mod)
assert status["status"] == "queued", f"expected queued, got {status}"
# No 'error' field on queued (it's not a failure)
assert "error" not in status or not status.get("error")
@pytest.mark.asyncio
async def test_queued_does_not_retry(self, delegation_mocks):
# The retry loop is for transient transport errors. A 202+queued
# is NOT a failure to retry against — the platform's drain will
# deliver the eventual reply. Retrying would just re-queue the
# same task and double-count it.
mod, *_ = delegation_mocks
client, mock_cls = _make_mock_client(
a2a_status=202,
a2a_payload={"queued": True},
)
with patch("httpx.AsyncClient", mock_cls):
await _invoke_and_wait(mod)
# The mock is shared across all AsyncClient calls (record, A2A,
# notify, update), so total post count includes platform-sync
# bookkeeping POSTs too. Only count the A2A POST itself —
# identified by URL matching the target's /a2a endpoint.
a2a_calls = [
c for c in client.post.await_args_list
if c.args and c.args[0] == "http://peer:8000"
]
assert len(a2a_calls) == 1, (
f"queued should not retry the A2A POST; got {len(a2a_calls)} A2A calls"
)
@pytest.mark.asyncio
async def test_202_without_queued_flag_falls_through(self, delegation_mocks):
# A bare 202 with no {queued: true} marker is NOT the platform's
# queue signal — could be a misbehaving proxy or a future protocol
# revision. Don't treat it as queued. Falls through to the existing
# retry-then-FAILED path.
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client(
a2a_status=202,
a2a_payload={"some_other_field": "value"},
)
with patch("httpx.AsyncClient", mock_cls):
status = await _invoke_and_wait(mod)
assert status["status"] == "failed", (
f"bare 202 should not be treated as queued, expected failed, got {status}"
)
class TestQueuedLazyRefresh:
"""When a delegation is QUEUED, check_delegation_status must lazily
refresh from the platform's GET /delegations to pick up drain-stitch
completions. Without this refresh, the LLM sees "queued" forever
because the platform never pushes back to the runtime.
Pre-fix the docstring told the LLM to wait on QUEUED. With no refresh
path, "wait" was permanent. These tests pin the refresh behavior so
the docstring is actually load-bearing."""
@pytest.mark.asyncio
async def test_queued_resolves_to_completed_via_lazy_refresh(self, delegation_mocks):
mod, *_ = delegation_mocks
# Step 1: invoke delegation, peer returns 202+queued, local
# status becomes QUEUED.
_, mock_cls_queued = _make_mock_client(
a2a_status=202,
a2a_payload={"queued": True},
)
with patch("httpx.AsyncClient", mock_cls_queued):
initial = await _invoke_and_wait(mod)
assert initial["status"] == "queued"
task_id = next(iter(mod._delegations))
# Step 2: simulate platform's drain having stitched a completed
# result. GET /workspaces/<self>/delegations now returns a
# 'completed' delegate_result row matching our task_id.
list_response = MagicMock()
list_response.status_code = 200
list_response.json.return_value = [
{
"delegation_id": task_id,
"type": "delegation",
"status": "completed",
"summary": "Delegation completed (peer reply)",
"response_preview": "the peer's actual reply text",
"source_id": "ws-self",
"target_id": "target",
},
]
refresh_client = AsyncMock()
refresh_client.get = AsyncMock(return_value=list_response)
refresh_client.post = AsyncMock(return_value=MagicMock(status_code=200))
refresh_cls = MagicMock()
refresh_cls.return_value.__aenter__ = AsyncMock(return_value=refresh_client)
refresh_cls.return_value.__aexit__ = AsyncMock(return_value=False)
with patch("httpx.AsyncClient", refresh_cls):
fn = mod.check_delegation_status
if hasattr(fn, "ainvoke"):
refreshed = await fn.ainvoke({"task_id": task_id})
else:
refreshed = await fn(task_id=task_id)
assert refreshed["status"] == "completed", (
f"lazy refresh should advance QUEUED → completed; got {refreshed}"
)
assert refreshed.get("result") == "the peer's actual reply text"
@pytest.mark.asyncio
async def test_queued_resolves_to_failed_via_lazy_refresh(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls_queued = _make_mock_client(
a2a_status=202,
a2a_payload={"queued": True},
)
with patch("httpx.AsyncClient", mock_cls_queued):
await _invoke_and_wait(mod)
task_id = next(iter(mod._delegations))
list_response = MagicMock()
list_response.status_code = 200
list_response.json.return_value = [
{
"delegation_id": task_id,
"type": "delegation",
"status": "failed",
"error": "peer timed out after 30 min",
"source_id": "ws-self",
"target_id": "target",
},
]
refresh_client = AsyncMock()
refresh_client.get = AsyncMock(return_value=list_response)
refresh_client.post = AsyncMock(return_value=MagicMock(status_code=200))
refresh_cls = MagicMock()
refresh_cls.return_value.__aenter__ = AsyncMock(return_value=refresh_client)
refresh_cls.return_value.__aexit__ = AsyncMock(return_value=False)
with patch("httpx.AsyncClient", refresh_cls):
fn = mod.check_delegation_status
if hasattr(fn, "ainvoke"):
refreshed = await fn.ainvoke({"task_id": task_id})
else:
refreshed = await fn(task_id=task_id)
assert refreshed["status"] == "failed"
assert refreshed.get("error") == "peer timed out after 30 min"
@pytest.mark.asyncio
async def test_queued_stays_queued_when_platform_not_resolved(self, delegation_mocks):
# Realistic case: LLM polls before platform's drain has fired.
# Refresh sees only the queued row → no state change. Subsequent
# poll will retry.
mod, *_ = delegation_mocks
_, mock_cls_queued = _make_mock_client(
a2a_status=202,
a2a_payload={"queued": True},
)
with patch("httpx.AsyncClient", mock_cls_queued):
await _invoke_and_wait(mod)
task_id = next(iter(mod._delegations))
list_response = MagicMock()
list_response.status_code = 200
list_response.json.return_value = [
{
"delegation_id": task_id,
"type": "delegation",
"status": "queued", # not yet resolved
"summary": "Delegation queued — target at capacity",
"source_id": "ws-self",
"target_id": "target",
},
]
refresh_client = AsyncMock()
refresh_client.get = AsyncMock(return_value=list_response)
refresh_client.post = AsyncMock(return_value=MagicMock(status_code=200))
refresh_cls = MagicMock()
refresh_cls.return_value.__aenter__ = AsyncMock(return_value=refresh_client)
refresh_cls.return_value.__aexit__ = AsyncMock(return_value=False)
with patch("httpx.AsyncClient", refresh_cls):
fn = mod.check_delegation_status
if hasattr(fn, "ainvoke"):
refreshed = await fn.ainvoke({"task_id": task_id})
else:
refreshed = await fn(task_id=task_id)
assert refreshed["status"] == "queued"
@pytest.mark.asyncio
async def test_refresh_is_safe_when_platform_unreachable(self, delegation_mocks):
# Platform GET fails (network blip). Refresh must not raise —
# local state stays QUEUED so the next poll retries.
mod, *_ = delegation_mocks
_, mock_cls_queued = _make_mock_client(
a2a_status=202,
a2a_payload={"queued": True},
)
with patch("httpx.AsyncClient", mock_cls_queued):
await _invoke_and_wait(mod)
task_id = next(iter(mod._delegations))
refresh_client = AsyncMock()
refresh_client.get = AsyncMock(side_effect=httpx.ConnectError("network down"))
refresh_client.post = AsyncMock(return_value=MagicMock(status_code=200))
refresh_cls = MagicMock()
refresh_cls.return_value.__aenter__ = AsyncMock(return_value=refresh_client)
refresh_cls.return_value.__aexit__ = AsyncMock(return_value=False)
with patch("httpx.AsyncClient", refresh_cls):
fn = mod.check_delegation_status
if hasattr(fn, "ainvoke"):
refreshed = await fn.ainvoke({"task_id": task_id})
else:
refreshed = await fn(task_id=task_id)
# Doesn't raise; local state preserved.
assert refreshed["status"] == "queued"
class TestA2AErrors:
@pytest.mark.asyncio
async def test_rpc_error(self, delegation_mocks):
mod, *_ = delegation_mocks
_, mock_cls = _make_mock_client(
a2a_payload={"error": {"message": "internal error"}}
)
with patch("httpx.AsyncClient", mock_cls):
status = await _invoke_and_wait(mod)
assert status["status"] == "failed"
@pytest.mark.asyncio
async def test_network_error(self, delegation_mocks):
mod, *_ = delegation_mocks
mock_client, mock_cls = _make_mock_client()
mock_client.post = AsyncMock(side_effect=httpx.ConnectError("refused"))
with patch("httpx.AsyncClient", mock_cls):
status = await _invoke_and_wait(mod)
assert status["status"] == "failed"
assert "refused" in status.get("error", "")
# ---------- #64: platform-mirroring helpers ----------
import asyncio as _asyncio_64
from unittest.mock import AsyncMock as _AsyncMock_64, patch as _patch_64
def test_record_delegation_on_platform_fires_http_post(delegation_mocks):
"""Agent registers the delegation on the platform so GET /delegations sees it."""
mod, _, _, _ = delegation_mocks
calls = []
class FakeClient:
def __init__(self, *a, **kw): pass
async def __aenter__(self): return self
async def __aexit__(self, *a): return False
async def post(self, url, json=None):
calls.append({"url": url, "json": json})
class R:
status_code = 202
return R()
with _patch_64.object(mod.httpx, "AsyncClient", FakeClient):
with _patch_64.object(mod, "WORKSPACE_ID", "src-ws"), \
_patch_64.object(mod, "PLATFORM_URL", "http://platform"):
_asyncio_64.run(
mod._record_delegation_on_platform("task-1", "target-ws", "hello")
)
assert len(calls) == 1
assert calls[0]["url"] == "http://platform/workspaces/src-ws/delegations/record"
body = calls[0]["json"]
assert body == {"target_id": "target-ws", "task": "hello", "delegation_id": "task-1"}
def test_record_delegation_on_platform_best_effort_on_error(delegation_mocks):
"""Platform unreachable must NOT block the A2A delegation path."""
mod, _, _, _ = delegation_mocks
class FailingClient:
def __init__(self, *a, **kw): pass
async def __aenter__(self): return self
async def __aexit__(self, *a): return False
async def post(self, *a, **kw):
raise RuntimeError("platform unreachable")
with _patch_64.object(mod.httpx, "AsyncClient", FailingClient):
with _patch_64.object(mod, "WORKSPACE_ID", "src-ws"), \
_patch_64.object(mod, "PLATFORM_URL", "http://platform"):
# Must not raise
_asyncio_64.run(
mod._record_delegation_on_platform("task-1", "target-ws", "hello")
)
def test_update_delegation_on_platform_completed(delegation_mocks):
mod, _, _, _ = delegation_mocks
calls = []
class FakeClient:
def __init__(self, *a, **kw): pass
async def __aenter__(self): return self
async def __aexit__(self, *a): return False
async def post(self, url, json=None):
calls.append({"url": url, "json": json})
class R:
status_code = 200
return R()
with _patch_64.object(mod.httpx, "AsyncClient", FakeClient):
with _patch_64.object(mod, "WORKSPACE_ID", "src-ws"), \
_patch_64.object(mod, "PLATFORM_URL", "http://platform"):
_asyncio_64.run(
mod._update_delegation_on_platform(
"task-1", "completed", "", "the result text"
)
)
assert calls[0]["url"] == "http://platform/workspaces/src-ws/delegations/task-1/update"
assert calls[0]["json"]["status"] == "completed"
assert calls[0]["json"]["response_preview"] == "the result text"
def test_update_delegation_on_platform_truncates_large_preview(delegation_mocks):
"""500-char cap protects log volume + mirrors the platform's 300-char truncate."""
mod, _, _, _ = delegation_mocks
calls = []
class FakeClient:
def __init__(self, *a, **kw): pass
async def __aenter__(self): return self
async def __aexit__(self, *a): return False
async def post(self, url, json=None):
calls.append({"url": url, "json": json})
class R:
status_code = 200
return R()
huge = "X" * 10000
with _patch_64.object(mod.httpx, "AsyncClient", FakeClient):
with _patch_64.object(mod, "WORKSPACE_ID", "src-ws"), \
_patch_64.object(mod, "PLATFORM_URL", "http://platform"):
_asyncio_64.run(
mod._update_delegation_on_platform("task-1", "completed", "", huge)
)
assert len(calls[0]["json"]["response_preview"]) == 500