mirror of
https://github.com/dograh-hq/dograh.git
synced 2026-06-07 07:55:16 +02:00
chore: update docs for pre-call data fetch
This commit is contained in:
parent
79ff04d8a9
commit
418592178c
7 changed files with 142 additions and 45 deletions
|
|
@ -15,6 +15,29 @@ from api.utils.credential_auth import build_auth_header
|
|||
PRE_CALL_FETCH_TIMEOUT_SECONDS = 10
|
||||
|
||||
|
||||
def _extract_initial_context(response_data: Dict[str, Any]) -> Dict[str, Any]:
|
||||
"""Pull the context variables out of a pre-call fetch response.
|
||||
|
||||
The canonical key is ``initial_context``. The legacy ``dynamic_variables``
|
||||
key is still accepted for backward compatibility, so existing endpoints
|
||||
keep working; ``initial_context`` takes precedence when both are present.
|
||||
|
||||
Either key may appear at the top level or nested under ``call_inbound``:
|
||||
{"call_inbound": {"initial_context": {...}}} | {"initial_context": {...}}
|
||||
{"call_inbound": {"dynamic_variables": {...}}} | {"dynamic_variables": {...}}
|
||||
"""
|
||||
container = response_data.get("call_inbound")
|
||||
if not isinstance(container, dict):
|
||||
container = response_data
|
||||
|
||||
for key in ("initial_context", "dynamic_variables"):
|
||||
value = container.get(key)
|
||||
if isinstance(value, dict):
|
||||
return value
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
async def execute_pre_call_fetch(
|
||||
*,
|
||||
url: str,
|
||||
|
|
@ -77,24 +100,16 @@ async def execute_pre_call_fetch(
|
|||
)
|
||||
return {}
|
||||
|
||||
# Extract dynamic_variables from Retell-compatible response
|
||||
# Supports: {call_inbound: {dynamic_variables: {...}}}
|
||||
# or: {dynamic_variables: {...}}
|
||||
dynamic_vars = {}
|
||||
call_inbound = response_data.get("call_inbound")
|
||||
if isinstance(call_inbound, dict):
|
||||
dynamic_vars = call_inbound.get("dynamic_variables", {})
|
||||
elif "dynamic_variables" in response_data:
|
||||
dynamic_vars = response_data["dynamic_variables"]
|
||||
|
||||
if not isinstance(dynamic_vars, dict):
|
||||
dynamic_vars = {}
|
||||
# Extract the variables to merge into initial_context. Prefers
|
||||
# the canonical `initial_context` key, falling back to the
|
||||
# legacy `dynamic_variables` key for backward compatibility.
|
||||
initial_context_vars = _extract_initial_context(response_data)
|
||||
|
||||
logger.info(
|
||||
f"Pre-call fetch: success ({response.status_code}), "
|
||||
f"dynamic_variables keys: {list(dynamic_vars.keys())}"
|
||||
f"initial_context keys: {list(initial_context_vars.keys())}"
|
||||
)
|
||||
return dynamic_vars
|
||||
return initial_context_vars
|
||||
else:
|
||||
logger.warning(
|
||||
f"Pre-call fetch: HTTP {response.status_code} - "
|
||||
|
|
|
|||
66
api/tests/test_pre_call_fetch.py
Normal file
66
api/tests/test_pre_call_fetch.py
Normal file
|
|
@ -0,0 +1,66 @@
|
|||
from api.services.pipecat.pre_call_fetch import _extract_initial_context
|
||||
|
||||
|
||||
class TestExtractInitialContext:
|
||||
"""Tests for _extract_initial_context, the pre-call fetch response parser."""
|
||||
|
||||
def test_initial_context_nested_under_call_inbound(self):
|
||||
"""The canonical `initial_context` key nested under `call_inbound`."""
|
||||
response = {"call_inbound": {"initial_context": {"customer_name": "Jane"}}}
|
||||
assert _extract_initial_context(response) == {"customer_name": "Jane"}
|
||||
|
||||
def test_initial_context_at_top_level(self):
|
||||
"""The canonical `initial_context` key at the top level."""
|
||||
response = {"initial_context": {"customer_name": "Jane"}}
|
||||
assert _extract_initial_context(response) == {"customer_name": "Jane"}
|
||||
|
||||
def test_legacy_dynamic_variables_nested(self):
|
||||
"""The legacy `dynamic_variables` key still works nested under `call_inbound`."""
|
||||
response = {"call_inbound": {"dynamic_variables": {"customer_name": "Jane"}}}
|
||||
assert _extract_initial_context(response) == {"customer_name": "Jane"}
|
||||
|
||||
def test_legacy_dynamic_variables_at_top_level(self):
|
||||
"""The legacy `dynamic_variables` key still works at the top level."""
|
||||
response = {"dynamic_variables": {"customer_name": "Jane"}}
|
||||
assert _extract_initial_context(response) == {"customer_name": "Jane"}
|
||||
|
||||
def test_initial_context_takes_precedence_over_legacy(self):
|
||||
"""When both keys are present, `initial_context` wins."""
|
||||
response = {
|
||||
"call_inbound": {
|
||||
"initial_context": {"source": "new"},
|
||||
"dynamic_variables": {"source": "legacy"},
|
||||
}
|
||||
}
|
||||
assert _extract_initial_context(response) == {"source": "new"}
|
||||
|
||||
def test_falls_back_to_legacy_when_initial_context_not_a_dict(self):
|
||||
"""A non-dict `initial_context` falls back to `dynamic_variables`."""
|
||||
response = {
|
||||
"initial_context": None,
|
||||
"dynamic_variables": {"customer_name": "Jane"},
|
||||
}
|
||||
assert _extract_initial_context(response) == {"customer_name": "Jane"}
|
||||
|
||||
def test_nested_values_preserved(self):
|
||||
"""Nested objects pass through untouched for dot-notation access."""
|
||||
response = {
|
||||
"call_inbound": {
|
||||
"initial_context": {"customer": {"address": {"city": "LA"}}}
|
||||
}
|
||||
}
|
||||
assert _extract_initial_context(response) == {
|
||||
"customer": {"address": {"city": "LA"}}
|
||||
}
|
||||
|
||||
def test_empty_when_no_known_keys(self):
|
||||
"""A response with neither key yields an empty dict."""
|
||||
assert _extract_initial_context({"call_inbound": {"agent_id": 1}}) == {}
|
||||
|
||||
def test_empty_when_call_inbound_missing(self):
|
||||
"""No `call_inbound` and no top-level keys yields an empty dict."""
|
||||
assert _extract_initial_context({}) == {}
|
||||
|
||||
def test_non_dict_vars_yield_empty(self):
|
||||
"""A non-dict value under a known key yields an empty dict."""
|
||||
assert _extract_initial_context({"initial_context": "nope"}) == {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue