Connector calls, semantic rules, and DuckDB memory keep long runs stable, and stream retry stops chats from stalling. Co-authored-by: Cursor <cursoragent@cursor.com>
44 lines
1.2 KiB
Python
44 lines
1.2 KiB
Python
from __future__ import annotations
|
|
|
|
import asyncio
|
|
from collections.abc import AsyncIterator
|
|
|
|
import pytest
|
|
|
|
from kamidso.api.sse import SSE_HEADERS, SSE_PING, with_sse_keepalive
|
|
|
|
|
|
def test_sse_headers_do_not_ask_proxies_to_reuse_the_socket():
|
|
assert "Connection" not in SSE_HEADERS
|
|
assert SSE_HEADERS["X-Accel-Buffering"] == "no"
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_keepalive_emits_ping_while_upstream_is_idle():
|
|
async def slow() -> AsyncIterator[str]:
|
|
await asyncio.sleep(0.05)
|
|
yield 'data: {"ok": true}\n\n'
|
|
|
|
chunks: list[str] = []
|
|
async for chunk in with_sse_keepalive(slow(), interval=0.02):
|
|
chunks.append(chunk)
|
|
|
|
assert any(item == SSE_PING for item in chunks)
|
|
assert any('"ok": true' in item for item in chunks)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_keepalive_cancels_pending_chunk_when_consumer_stops():
|
|
released = asyncio.Event()
|
|
|
|
async def blocked() -> AsyncIterator[str]:
|
|
await released.wait()
|
|
yield 'data: {"late": true}\n\n'
|
|
|
|
gen = with_sse_keepalive(blocked(), interval=0.05)
|
|
first = await gen.__anext__()
|
|
assert first == SSE_PING
|
|
await gen.aclose()
|
|
released.set()
|
|
await asyncio.sleep(0.02)
|