refactor(agent): remove memory agent, simplify runtime config system
This commit is contained in:
@@ -5,17 +5,23 @@ from uuid import UUID, uuid4
|
||||
|
||||
import pytest
|
||||
|
||||
from core.automation.scheduler import (
|
||||
AutomationSchedulerService,
|
||||
_compute_next_run_at,
|
||||
from models.automation_jobs import AutomationJob as OrmAutomationJob, ScheduleType
|
||||
from schemas.automation import (
|
||||
RuntimeConfig,
|
||||
)
|
||||
from models.automation_jobs import ScheduleType
|
||||
from schemas.automation.config import AutomationJobConfig
|
||||
from schemas.automation.scheduler import DueAutomationJob
|
||||
from v1.automation_jobs.service import AutomationJobsService, _compute_next_run_at
|
||||
|
||||
|
||||
class _FakeSession:
|
||||
async def commit(self) -> None:
|
||||
pass
|
||||
|
||||
async def rollback(self) -> None:
|
||||
pass
|
||||
|
||||
|
||||
class _FakeRepository:
|
||||
def __init__(self, jobs: list[DueAutomationJob]) -> None:
|
||||
def __init__(self, jobs: list[OrmAutomationJob]) -> None:
|
||||
self.jobs = jobs
|
||||
self.marked: list[tuple[UUID, datetime, datetime]] = []
|
||||
self.commits = 0
|
||||
@@ -23,30 +29,14 @@ class _FakeRepository:
|
||||
|
||||
async def list_due_jobs(
|
||||
self, *, now_utc: datetime, limit: int
|
||||
) -> list[DueAutomationJob]:
|
||||
) -> list[OrmAutomationJob]:
|
||||
del now_utc
|
||||
return self.jobs[:limit]
|
||||
|
||||
async def get_job_config(self, *, job_id: UUID) -> AutomationJobConfig:
|
||||
del job_id
|
||||
return AutomationJobConfig.model_validate(
|
||||
{
|
||||
"agent_type": "memory",
|
||||
"model_code": "qwen3.5-flash",
|
||||
"enabled_tools": ["calendar.read", "user.lookup"],
|
||||
"input_template": "auto input",
|
||||
"context": {
|
||||
"source": "latest_chat",
|
||||
"window_mode": "day",
|
||||
"window_count": 2,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
async def ensure_latest_chat_session(self, *, owner_id: UUID) -> UUID:
|
||||
async def get_or_create_chat_session(self, *, owner_id: UUID) -> UUID:
|
||||
return owner_id
|
||||
|
||||
async def mark_job_dispatched(
|
||||
async def update_job_schedule(
|
||||
self,
|
||||
*,
|
||||
job_id: UUID,
|
||||
@@ -55,57 +45,65 @@ class _FakeRepository:
|
||||
) -> None:
|
||||
self.marked.append((job_id, next_run_at, last_run_at))
|
||||
|
||||
async def commit(self) -> None:
|
||||
self.commits += 1
|
||||
|
||||
async def rollback(self) -> None:
|
||||
self.rollbacks += 1
|
||||
|
||||
|
||||
class _FakeQueue:
|
||||
def __init__(self) -> None:
|
||||
self.commands: list[dict[str, object]] = []
|
||||
|
||||
async def enqueue(
|
||||
self,
|
||||
*,
|
||||
command: dict[str, object],
|
||||
dedup_key: str | None,
|
||||
) -> str:
|
||||
del dedup_key
|
||||
self.commands.append(command)
|
||||
return "task-1"
|
||||
def _make_orm_job(
|
||||
*,
|
||||
job_id: UUID | None = None,
|
||||
owner_id: UUID | None = None,
|
||||
schedule_type: ScheduleType = ScheduleType.DAILY,
|
||||
next_run_at: datetime | None = None,
|
||||
) -> OrmAutomationJob:
|
||||
now = datetime(2026, 3, 19, 12, 0, tzinfo=timezone.utc)
|
||||
return OrmAutomationJob(
|
||||
id=job_id or uuid4(),
|
||||
owner_id=owner_id or uuid4(),
|
||||
title="Test Job",
|
||||
config={
|
||||
"enabled_tools": ["calendar.read", "user.lookup"],
|
||||
"context": {
|
||||
"source": "latest_chat",
|
||||
"window_mode": "day",
|
||||
"window_count": 2,
|
||||
},
|
||||
"input_template": "auto input: {date}",
|
||||
},
|
||||
schedule_type=schedule_type,
|
||||
run_at=now - timedelta(hours=1),
|
||||
next_run_at=next_run_at or now - timedelta(minutes=1),
|
||||
timezone="UTC",
|
||||
last_run_at=None,
|
||||
status="active",
|
||||
created_by=None,
|
||||
created_at=now - timedelta(days=1),
|
||||
updated_at=now - timedelta(hours=1),
|
||||
deleted_at=None,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_scan_and_dispatch_enqueues_memory_run_command() -> None:
|
||||
async def test_scan_and_dispatch_calls_dispatch_fn_with_runtime_config() -> None:
|
||||
now = datetime(2026, 3, 19, 12, 0, tzinfo=timezone.utc)
|
||||
owner_id = uuid4()
|
||||
job_id = uuid4()
|
||||
repo = _FakeRepository(
|
||||
jobs=[
|
||||
DueAutomationJob(
|
||||
id=job_id,
|
||||
owner_id=owner_id,
|
||||
schedule_type=ScheduleType.DAILY,
|
||||
timezone="UTC",
|
||||
next_run_at=now - timedelta(minutes=1),
|
||||
)
|
||||
]
|
||||
)
|
||||
queue = _FakeQueue()
|
||||
service = AutomationSchedulerService(repository=repo, queue=queue)
|
||||
repo = _FakeRepository(jobs=[_make_orm_job(job_id=job_id, owner_id=owner_id)])
|
||||
dispatched_calls: list[dict] = []
|
||||
|
||||
result = await service.scan_and_dispatch(now_utc=now, limit=10)
|
||||
async def dispatch_fn(**kwargs: object) -> None:
|
||||
dispatched_calls.append(kwargs)
|
||||
|
||||
service = AutomationJobsService(repository=repo, session=_FakeSession())
|
||||
|
||||
result = await service.scan_and_dispatch(
|
||||
now_utc=now, limit=10, dispatch_fn=dispatch_fn
|
||||
)
|
||||
|
||||
assert result.scanned == 1
|
||||
assert result.dispatched == 1
|
||||
assert len(queue.commands) == 1
|
||||
run_input = queue.commands[0]["run_input"]
|
||||
assert isinstance(run_input, dict)
|
||||
assert run_input["forwardedProps"] == {"agent_type": "memory"}
|
||||
assert queue.commands[0]["automation_job_id"] == str(job_id)
|
||||
assert repo.commits == 1
|
||||
assert len(dispatched_calls) == 1
|
||||
assert dispatched_calls[0]["owner_id"] == owner_id
|
||||
assert dispatched_calls[0]["runtime_config"] is not None
|
||||
cfg: RuntimeConfig = dispatched_calls[0]["runtime_config"]
|
||||
assert len(cfg.enabled_tools) == 2
|
||||
|
||||
|
||||
def test_compute_next_run_at_daily() -> None:
|
||||
|
||||
Reference in New Issue
Block a user