Refactor project structure and enhance backend integration
- Expanded package inclusion in `pyproject.toml` to support new modules. - Introduced new `adapters` and `protocol` packages for better organization. - Added backend adapter implementations for control plane integration. - Updated main application imports to reflect new package structure. - Removed deprecated core components and adjusted documentation accordingly. - Enhanced architecture documentation to clarify the new runtime and integration layers.
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
import aiohttp
|
||||
import pytest
|
||||
|
||||
from app.backend_adapters import (
|
||||
from adapters.control_plane.backend import (
|
||||
AssistantConfigSourceAdapter,
|
||||
LocalYamlAssistantConfigAdapter,
|
||||
build_backend_adapter,
|
||||
@@ -120,7 +120,7 @@ async def test_http_backend_adapter_create_call_record_posts_expected_payload(mo
|
||||
},
|
||||
)
|
||||
|
||||
monkeypatch.setattr("app.backend_adapters.aiohttp.ClientSession", _FakeClientSession)
|
||||
monkeypatch.setattr("adapters.control_plane.backend.aiohttp.ClientSession", _FakeClientSession)
|
||||
|
||||
config_dir = tmp_path / "assistants"
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
@@ -198,7 +198,7 @@ async def test_with_backend_url_uses_backend_for_assistant_config(monkeypatch, t
|
||||
_ = (url, json)
|
||||
return _FakeResponse(status=200, payload={"id": "call_1"})
|
||||
|
||||
monkeypatch.setattr("app.backend_adapters.aiohttp.ClientSession", _FakeClientSession)
|
||||
monkeypatch.setattr("adapters.control_plane.backend.aiohttp.ClientSession", _FakeClientSession)
|
||||
|
||||
config_dir = tmp_path / "assistants"
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
@@ -234,7 +234,7 @@ async def test_backend_mode_disabled_uses_local_assistant_config_even_with_url(m
|
||||
_ = timeout
|
||||
raise AssertionError("HTTP client should not be created when backend_mode=disabled")
|
||||
|
||||
monkeypatch.setattr("app.backend_adapters.aiohttp.ClientSession", _FailIfCalledClientSession)
|
||||
monkeypatch.setattr("adapters.control_plane.backend.aiohttp.ClientSession", _FailIfCalledClientSession)
|
||||
|
||||
config_dir = tmp_path / "assistants"
|
||||
config_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from core.session import Session
|
||||
from runtime.session.manager import Session
|
||||
|
||||
|
||||
def _session() -> Session:
|
||||
|
||||
@@ -3,7 +3,7 @@ import time
|
||||
|
||||
import pytest
|
||||
|
||||
from core.history_bridge import SessionHistoryBridge
|
||||
from runtime.history.bridge import SessionHistoryBridge
|
||||
|
||||
|
||||
class _FakeHistoryWriter:
|
||||
|
||||
@@ -4,10 +4,10 @@ from typing import Any, Dict, List
|
||||
|
||||
import pytest
|
||||
|
||||
from core.conversation import ConversationState
|
||||
from core.duplex_pipeline import DuplexPipeline
|
||||
from models.ws_v1 import OutputAudioPlayedMessage, ToolCallResultsMessage, parse_client_message
|
||||
from services.base import LLMStreamEvent
|
||||
from runtime.conversation import ConversationState
|
||||
from runtime.pipeline.duplex import DuplexPipeline
|
||||
from protocol.ws_v1.schema import OutputAudioPlayedMessage, ToolCallResultsMessage, parse_client_message
|
||||
from providers.common.base import LLMStreamEvent
|
||||
|
||||
|
||||
class _DummySileroVAD:
|
||||
@@ -86,9 +86,9 @@ class _CaptureGenerateLLM:
|
||||
|
||||
|
||||
def _build_pipeline(monkeypatch, llm_rounds: List[List[LLMStreamEvent]]) -> tuple[DuplexPipeline, List[Dict[str, Any]]]:
|
||||
monkeypatch.setattr("core.duplex_pipeline.SileroVAD", _DummySileroVAD)
|
||||
monkeypatch.setattr("core.duplex_pipeline.VADProcessor", _DummyVADProcessor)
|
||||
monkeypatch.setattr("core.duplex_pipeline.EouDetector", _DummyEouDetector)
|
||||
monkeypatch.setattr("runtime.pipeline.duplex.SileroVAD", _DummySileroVAD)
|
||||
monkeypatch.setattr("runtime.pipeline.duplex.VADProcessor", _DummyVADProcessor)
|
||||
monkeypatch.setattr("runtime.pipeline.duplex.EouDetector", _DummyEouDetector)
|
||||
|
||||
pipeline = DuplexPipeline(
|
||||
transport=_FakeTransport(),
|
||||
@@ -112,7 +112,7 @@ def _build_pipeline(monkeypatch, llm_rounds: List[List[LLMStreamEvent]]) -> tupl
|
||||
|
||||
def test_pipeline_uses_default_tools_from_settings(monkeypatch):
|
||||
monkeypatch.setattr(
|
||||
"core.duplex_pipeline.settings.tools",
|
||||
"runtime.pipeline.duplex.settings.tools",
|
||||
[
|
||||
"current_time",
|
||||
"calculator",
|
||||
@@ -141,7 +141,7 @@ def test_pipeline_uses_default_tools_from_settings(monkeypatch):
|
||||
|
||||
|
||||
def test_pipeline_exposes_unknown_string_tools_with_fallback_schema(monkeypatch):
|
||||
monkeypatch.setattr("core.duplex_pipeline.settings.tools", ["custom_system_cmd"])
|
||||
monkeypatch.setattr("runtime.pipeline.duplex.settings.tools", ["custom_system_cmd"])
|
||||
pipeline, _events = _build_pipeline(monkeypatch, [[LLMStreamEvent(type="done")]])
|
||||
|
||||
schemas = pipeline._resolved_tool_schemas()
|
||||
@@ -151,7 +151,7 @@ def test_pipeline_exposes_unknown_string_tools_with_fallback_schema(monkeypatch)
|
||||
|
||||
|
||||
def test_pipeline_assigns_default_client_executor_for_system_string_tools(monkeypatch):
|
||||
monkeypatch.setattr("core.duplex_pipeline.settings.tools", ["increase_volume"])
|
||||
monkeypatch.setattr("runtime.pipeline.duplex.settings.tools", ["increase_volume"])
|
||||
pipeline, _events = _build_pipeline(monkeypatch, [[LLMStreamEvent(type="done")]])
|
||||
|
||||
tool_call = {
|
||||
@@ -221,9 +221,9 @@ async def test_pipeline_applies_default_args_to_tool_call(monkeypatch):
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_generated_opener_prompt_uses_system_prompt_only(monkeypatch):
|
||||
monkeypatch.setattr("core.duplex_pipeline.SileroVAD", _DummySileroVAD)
|
||||
monkeypatch.setattr("core.duplex_pipeline.VADProcessor", _DummyVADProcessor)
|
||||
monkeypatch.setattr("core.duplex_pipeline.EouDetector", _DummyEouDetector)
|
||||
monkeypatch.setattr("runtime.pipeline.duplex.SileroVAD", _DummySileroVAD)
|
||||
monkeypatch.setattr("runtime.pipeline.duplex.VADProcessor", _DummyVADProcessor)
|
||||
monkeypatch.setattr("runtime.pipeline.duplex.EouDetector", _DummyEouDetector)
|
||||
|
||||
llm = _CaptureGenerateLLM("你好")
|
||||
pipeline = DuplexPipeline(
|
||||
@@ -662,7 +662,7 @@ async def test_server_tool_timeout_emits_504_and_continues(monkeypatch):
|
||||
"status": {"code": 200, "message": "ok"},
|
||||
}
|
||||
|
||||
monkeypatch.setattr("core.duplex_pipeline.execute_server_tool", _slow_execute)
|
||||
monkeypatch.setattr("runtime.pipeline.duplex.execute_server_tool", _slow_execute)
|
||||
|
||||
pipeline, events = _build_pipeline(
|
||||
monkeypatch,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import pytest
|
||||
|
||||
from core.tool_executor import execute_server_tool
|
||||
from tools.executor import execute_server_tool
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@@ -38,7 +38,7 @@ async def test_current_time_uses_local_system_clock(monkeypatch):
|
||||
async def _should_not_be_called(_tool_id):
|
||||
raise AssertionError("fetch_tool_resource should not be called for current_time")
|
||||
|
||||
monkeypatch.setattr("core.tool_executor.fetch_tool_resource", _should_not_be_called)
|
||||
monkeypatch.setattr("tools.executor.fetch_tool_resource", _should_not_be_called)
|
||||
|
||||
result = await execute_server_tool(
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import pytest
|
||||
|
||||
from core.session import Session, WsSessionState
|
||||
from models.ws_v1 import OutputAudioPlayedMessage, SessionStartMessage, parse_client_message
|
||||
from runtime.session.manager import Session, WsSessionState
|
||||
from protocol.ws_v1.schema import OutputAudioPlayedMessage, SessionStartMessage, parse_client_message
|
||||
|
||||
|
||||
def _session() -> Session:
|
||||
@@ -194,7 +194,7 @@ async def test_handle_session_start_requires_assistant_id_and_closes_transport()
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_session_start_applies_whitelisted_overrides_and_ignores_workflow(monkeypatch):
|
||||
monkeypatch.setattr("core.session.settings.ws_emit_config_resolved", False)
|
||||
monkeypatch.setattr("runtime.session.manager.settings.ws_emit_config_resolved", False)
|
||||
|
||||
session = Session.__new__(Session)
|
||||
session.id = "sess_start_ok"
|
||||
@@ -289,9 +289,9 @@ async def test_handle_session_start_applies_whitelisted_overrides_and_ignores_wo
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_session_start_emits_config_resolved_when_enabled(monkeypatch):
|
||||
monkeypatch.setattr("core.session.settings.ws_emit_config_resolved", True)
|
||||
monkeypatch.setattr("core.session.settings.ws_protocol_version", "v1-custom")
|
||||
monkeypatch.setattr("core.session.settings.default_codec", "pcmu")
|
||||
monkeypatch.setattr("runtime.session.manager.settings.ws_emit_config_resolved", True)
|
||||
monkeypatch.setattr("runtime.session.manager.settings.ws_protocol_version", "v1-custom")
|
||||
monkeypatch.setattr("runtime.session.manager.settings.default_codec", "pcmu")
|
||||
|
||||
session = Session.__new__(Session)
|
||||
session.id = "sess_start_emit_config"
|
||||
@@ -385,8 +385,8 @@ async def test_handle_session_start_emits_config_resolved_when_enabled(monkeypat
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_audio_uses_chunk_size_for_frame_validation(monkeypatch):
|
||||
monkeypatch.setattr("core.session.settings.sample_rate", 16000)
|
||||
monkeypatch.setattr("core.session.settings.chunk_size_ms", 10)
|
||||
monkeypatch.setattr("runtime.session.manager.settings.sample_rate", 16000)
|
||||
monkeypatch.setattr("runtime.session.manager.settings.chunk_size_ms", 10)
|
||||
|
||||
session = Session.__new__(Session)
|
||||
session.id = "sess_chunk_frame"
|
||||
|
||||
Reference in New Issue
Block a user