Playwright response -> OpenAI compatible SSE generator.
(
page: AsyncPage,
logger: logging.Logger,
req_id: str,
model_name_for_stream: str,
request: ChatCompletionRequest,
check_client_disconnected: Callable[[str], bool],
completion_event: Event,
prompt_length: int,
timeout: float,
)
| 498 | |
| 499 | |
| 500 | async def gen_sse_from_playwright( |
| 501 | page: AsyncPage, |
| 502 | logger: logging.Logger, |
| 503 | req_id: str, |
| 504 | model_name_for_stream: str, |
| 505 | request: ChatCompletionRequest, |
| 506 | check_client_disconnected: Callable[[str], bool], |
| 507 | completion_event: Event, |
| 508 | prompt_length: int, |
| 509 | timeout: float, |
| 510 | ) -> AsyncGenerator[str, None]: |
| 511 | """Playwright response -> OpenAI compatible SSE generator.""" |
| 512 | from browser_utils.page_controller import PageController |
| 513 | from models import ClientDisconnectedError |
| 514 | |
| 515 | set_request_id(req_id) |
| 516 | data_receiving = False |
| 517 | try: |
| 518 | page_controller = PageController(page, logger, req_id) |
| 519 | # Use get_response_with_function_calls which handles both content and functions |
| 520 | response_data = await page_controller.get_response_with_function_calls( |
| 521 | check_client_disconnected, prompt_length=prompt_length, timeout=timeout |
| 522 | ) |
| 523 | final_content = response_data.get("content", "") |
| 524 | function_calls = response_data.get("function_calls", []) |
| 525 | |
| 526 | data_receiving = True |
| 527 | lines = final_content.split("\n") |
| 528 | for line_idx, line in enumerate(lines): |
| 529 | try: |
| 530 | check_client_disconnected( |
| 531 | f"Playwright stream generator loop ({req_id}): " |
| 532 | ) |
| 533 | except ClientDisconnectedError: |
| 534 | if data_receiving and not completion_event.is_set(): |
| 535 | completion_event.set() |
| 536 | break |
| 537 | if line: |
| 538 | chunk_size = 5 |
| 539 | for i in range(0, len(line), chunk_size): |
| 540 | yield generate_sse_chunk( |
| 541 | line[i : i + chunk_size], req_id, model_name_for_stream |
| 542 | ) |
| 543 | await asyncio.sleep(0.03) |
| 544 | if line_idx < len(lines) - 1: |
| 545 | yield generate_sse_chunk("\n", req_id, model_name_for_stream) |
| 546 | await asyncio.sleep(0.01) |
| 547 | |
| 548 | usage_stats = calculate_usage_stats( |
| 549 | [msg.model_dump() for msg in request.messages], final_content, "" |
| 550 | ) |
| 551 | total_tokens = usage_stats.get("total_tokens", 0) |
| 552 | GlobalState.increment_token_count(total_tokens) |
| 553 | from api_utils.server_state import state |
| 554 | |
| 555 | if ( |
| 556 | hasattr(state, "current_auth_profile_path") |
| 557 | and state.current_auth_profile_path |