diff --git a/signalwire/signalwire/ai_chat/gateway.py b/signalwire/signalwire/ai_chat/gateway.py index e2f4f5f..acc916d 100644 --- a/signalwire/signalwire/ai_chat/gateway.py +++ b/signalwire/signalwire/ai_chat/gateway.py @@ -481,8 +481,13 @@ async def proxy(request: Request) -> Response: return JSONResponse({"status": "ended"}, headers=cors) if method == "create_conversation": + # prepare() decides whether a timeout applies; dropping it here + # would report one number to the browser below while the + # service quietly keeps its own default. info = await self._client.create_conversation( - params["id"], config_url=params["config_url"] + params["id"], + config_url=params["config_url"], + timeout=params.get("conversation_timeout"), ) if minted: cors["X-Chat-Handle"] = minted diff --git a/tests/unit/ai_chat/test_gateway.py b/tests/unit/ai_chat/test_gateway.py index 9e78d67..f554c64 100644 --- a/tests/unit/ai_chat/test_gateway.py +++ b/tests/unit/ai_chat/test_gateway.py @@ -541,3 +541,40 @@ async def test_start_then_reload_replays_the_same_conversation(gateway, service) assert "messages" in replay.json() # and it asked the service for the conversation the handle names assert service.seen[-1]["params"]["id"] == gateway.read_handle(handle) + + +async def test_start_forwards_the_configured_timeout_upstream(service: Any) -> None: + """prepare() puts conversation_timeout in the start params, but the HTTP + dispatch used to rebuild the create_conversation call and drop it — the + browser was told 900 while the service kept its 3600 default. The number + the page schedules its idle warning around must be the number the service + actually enforces.""" + gw = make_gateway( + service, + allowed_origins=["https://shop.example.com"], + conversation_timeout=900, + ) + try: + async with asgi(gw) as http: + started = await http.post( + "/chat/", json={"method": "start"}, headers=HEADERS + ) + assert started.status_code == 200 + assert started.json()["timeout"] == 900 + sent = service.seen[-1] + assert sent["method"] == "create_conversation" + assert sent["params"]["conversation_timeout"] == 900 + + # The chat path auto-creates too, and takes the same timeout. + handle = started.headers["x-chat-handle"] + chatted = await http.post( + "/chat/", + json={"message": "hi", "handle": handle}, + headers=HEADERS, + ) + assert chatted.status_code == 200 + sent = service.seen[-1] + assert sent["method"] == "chat" + assert sent["params"]["conversation_timeout"] == 900 + finally: + await gw._client.close()