mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
Smoke run 4 crashed with AttributeError: 'SessionForTasksCreateRequest' object has no attribute 'config' when main-pm called open_session. The service _build_session_request reads req.config.max_message_count (model has nested config). The gateway was passing the API schema SessionForTasksCreateRequest (flat fields, no config attribute at all) — so `req.config` blew up with AttributeError, not the safer None. Fix: gateway now constructs SessionForTasksCreate (the model) with the enum-typed relationship_type, matching what the route at roboco/api/routes/sessions.py:230 does. Unknown relationship strings fall back to DISCUSSION. Two regression tests pin the contract: service receives the model; invalid relationship_type defaults to DISCUSSION.
100 lines
3.3 KiB
Python
100 lines
3.3 KiB
Python
"""Smoke-4: open_session must pass the model schema (not the API schema) to
|
|
the messaging service.
|
|
|
|
Smoke run 4 surfaced an AttributeError because content_actions.open_session
|
|
constructed a `SessionForTasksCreateRequest` (API schema, flat fields) but
|
|
`MessagingService._build_session_request` reads `req.config.max_message_count`
|
|
(the model has nested `config`). Two schemas, one expected, one passed.
|
|
|
|
This test pins the contract: the gateway constructs the model and the
|
|
service receives the model.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from unittest.mock import AsyncMock, MagicMock
|
|
from uuid import uuid4
|
|
|
|
import pytest
|
|
from roboco.models.session import SessionForTasksCreate, SessionTaskRelationshipType
|
|
from roboco.services.gateway.content_actions import ContentActions, ContentActionsDeps
|
|
|
|
|
|
def _make_deps(**overrides: object) -> ContentActionsDeps:
|
|
base: dict[str, object] = {
|
|
"task": AsyncMock(),
|
|
"git": AsyncMock(),
|
|
"messaging": AsyncMock(),
|
|
"a2a": AsyncMock(),
|
|
"journal": AsyncMock(),
|
|
"workspace": AsyncMock(),
|
|
"notifications": AsyncMock(),
|
|
}
|
|
base.update(overrides)
|
|
return ContentActionsDeps(**base)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_open_session_passes_model_schema_to_service() -> None:
|
|
"""The service must receive a SessionForTasksCreate (model), not the API schema."""
|
|
agent_id = uuid4()
|
|
task_id = uuid4()
|
|
pm_agent = MagicMock(role="cell_pm")
|
|
|
|
task_svc = AsyncMock()
|
|
task_svc.agent_for.return_value = pm_agent
|
|
|
|
session_row = MagicMock(id=uuid4())
|
|
messaging_svc = AsyncMock()
|
|
messaging_svc.create_session_for_tasks.return_value = (session_row, [])
|
|
|
|
deps = _make_deps(task=task_svc, messaging=messaging_svc)
|
|
actions = ContentActions(deps)
|
|
|
|
env = await actions.open_session(
|
|
agent_id=agent_id,
|
|
task_id=task_id,
|
|
channel="backend-cell",
|
|
topic="discuss the plan",
|
|
relationship_type="discussion",
|
|
group_id=None,
|
|
)
|
|
|
|
assert env.error is None, (
|
|
f"open_session returned error: {env.error} / {env.message}"
|
|
)
|
|
messaging_svc.create_session_for_tasks.assert_awaited_once()
|
|
call = messaging_svc.create_session_for_tasks.await_args
|
|
passed_req = call.kwargs["req"]
|
|
assert isinstance(passed_req, SessionForTasksCreate), (
|
|
f"expected SessionForTasksCreate (model), got {type(passed_req).__name__}. "
|
|
f"The service reads req.config.* which only exists on the model."
|
|
)
|
|
|
|
|
|
@pytest.mark.asyncio
|
|
async def test_open_session_unknown_relationship_falls_back_to_discussion() -> None:
|
|
"""Invalid relationship_type string defaults to DISCUSSION enum."""
|
|
pm_agent = MagicMock(role="main_pm")
|
|
task_svc = AsyncMock()
|
|
task_svc.agent_for.return_value = pm_agent
|
|
|
|
session_row = MagicMock(id=uuid4())
|
|
messaging_svc = AsyncMock()
|
|
messaging_svc.create_session_for_tasks.return_value = (session_row, [])
|
|
|
|
deps = _make_deps(task=task_svc, messaging=messaging_svc)
|
|
actions = ContentActions(deps)
|
|
|
|
await actions.open_session(
|
|
agent_id=uuid4(),
|
|
task_id=uuid4(),
|
|
channel="backend-cell",
|
|
topic="discuss",
|
|
relationship_type="nonsense-type-not-in-enum",
|
|
group_id=None,
|
|
)
|
|
|
|
passed_req = messaging_svc.create_session_for_tasks.await_args.kwargs["req"]
|
|
assert passed_req.relationship_type == SessionTaskRelationshipType.DISCUSSION
|