|
1 | 1 | import pytest |
2 | 2 |
|
3 | | -from realtime import ( |
| 3 | +from solana_agent.interfaces.providers.realtime import ( |
4 | 4 | RealtimeSessionOptions, |
5 | 5 | RealtimeChunk, |
6 | 6 | separate_audio_chunks, |
@@ -370,3 +370,106 @@ def test_abstract_methods_exist(self): |
370 | 370 |
|
371 | 371 | method = getattr(BaseRealtimeSession, method_name) |
372 | 372 | assert callable(method), f"Method {method_name} is not callable" |
| 373 | + |
| 374 | + |
| 375 | +class _ConcreteRealtimeSession( |
| 376 | + BaseRealtimeSession |
| 377 | +): # pragma: no cover - used only for coverage tests |
| 378 | + async def connect(self) -> None: |
| 379 | + pass |
| 380 | + |
| 381 | + async def close(self) -> None: |
| 382 | + pass |
| 383 | + |
| 384 | + async def update_session(self, session_patch): |
| 385 | + pass |
| 386 | + |
| 387 | + async def append_audio(self, pcm16_bytes: bytes) -> None: |
| 388 | + pass |
| 389 | + |
| 390 | + async def commit_input(self) -> None: |
| 391 | + pass |
| 392 | + |
| 393 | + async def clear_input(self) -> None: |
| 394 | + pass |
| 395 | + |
| 396 | + async def create_response(self, response_patch=None) -> None: |
| 397 | + pass |
| 398 | + |
| 399 | + def iter_events(self): |
| 400 | + async def _g(): |
| 401 | + if False: |
| 402 | + yield # pragma: no cover |
| 403 | + |
| 404 | + return _g() |
| 405 | + |
| 406 | + def iter_output_audio(self): |
| 407 | + async def _g(): |
| 408 | + if False: |
| 409 | + yield # pragma: no cover |
| 410 | + |
| 411 | + return _g() |
| 412 | + |
| 413 | + def iter_input_transcript(self): |
| 414 | + async def _g(): |
| 415 | + if False: |
| 416 | + yield # pragma: no cover |
| 417 | + |
| 418 | + return _g() |
| 419 | + |
| 420 | + def iter_output_transcript(self): |
| 421 | + async def _g(): |
| 422 | + if False: |
| 423 | + yield # pragma: no cover |
| 424 | + |
| 425 | + return _g() |
| 426 | + |
| 427 | + def set_tool_executor(self, executor): |
| 428 | + pass |
| 429 | + |
| 430 | + |
| 431 | +class TestRealtimeSessionOptionsTranscription: |
| 432 | + def test_transcription_defaults(self): |
| 433 | + opts = RealtimeSessionOptions() |
| 434 | + assert opts.transcription_model is None |
| 435 | + assert opts.transcription_language is None |
| 436 | + assert opts.transcription_prompt is None |
| 437 | + assert opts.transcription_noise_reduction is None |
| 438 | + assert opts.transcription_include_logprobs is False |
| 439 | + |
| 440 | + def test_transcription_custom(self): |
| 441 | + opts = RealtimeSessionOptions( |
| 442 | + transcription_model="whisper-1", |
| 443 | + transcription_language="en", |
| 444 | + transcription_prompt="domain context", |
| 445 | + transcription_noise_reduction=True, |
| 446 | + transcription_include_logprobs=True, |
| 447 | + ) |
| 448 | + assert opts.transcription_model == "whisper-1" |
| 449 | + assert opts.transcription_language == "en" |
| 450 | + assert opts.transcription_prompt == "domain context" |
| 451 | + assert opts.transcription_noise_reduction is True |
| 452 | + assert opts.transcription_include_logprobs is True |
| 453 | + |
| 454 | + |
| 455 | +@pytest.mark.asyncio |
| 456 | +class TestConcreteRealtimeSessionCoverage: |
| 457 | + async def test_instantiate_and_call_methods(self): |
| 458 | + sess = _ConcreteRealtimeSession() |
| 459 | + await sess.connect() |
| 460 | + await sess.update_session({"a": 1}) |
| 461 | + await sess.append_audio(b"\x00\x00") |
| 462 | + await sess.commit_input() |
| 463 | + await sess.clear_input() |
| 464 | + await sess.create_response({"response": 1}) |
| 465 | + sess.set_tool_executor(lambda name, args: None) # sync is fine for stub |
| 466 | + # Iterate through generators (they are empty) |
| 467 | + async for _ in sess.iter_events(): |
| 468 | + pass |
| 469 | + async for _ in sess.iter_output_audio(): |
| 470 | + pass |
| 471 | + async for _ in sess.iter_input_transcript(): |
| 472 | + pass |
| 473 | + async for _ in sess.iter_output_transcript(): |
| 474 | + pass |
| 475 | + await sess.close() |
0 commit comments