oclaw/tests/test_scheduler_viewer_username.py
oliver 51eef09801 Synthesize playbooks from structured prompts and inject prior-run context.
Legacy jobs with empty recipes (e.g. dying-gasp algorithms in prompt_text) now compile into durable playbooks on create/enqueue, and each run gets a short previous-run summary for continuity.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-10 23:59:27 +08:00

119 lines
4.3 KiB
Python

from __future__ import annotations
import os
import tempfile
import unittest
from pathlib import Path
from unittest.mock import MagicMock
from runtime.scheduler.session_resolver import resolve_scheduled_viewer_username
from runtime.scheduler.service import enqueue_scheduled_job_run
from svc.persistence.sqlite_store import SqliteStore
class ResolveScheduledViewerUsernameTests(unittest.TestCase):
def setUp(self) -> None:
self._tmp = tempfile.TemporaryDirectory(ignore_cleanup_errors=True)
self.db = Path(self._tmp.name) / "sched.sqlite"
os.environ["OPS_ASSISTANT_DB_PATH"] = str(self.db)
self.store = SqliteStore(str(self.db))
t = self.store.create_tenant("Team")
self.tenant_id = str(t["id"])
self.admin = self.store.create_user_account(
tenant_id=self.tenant_id,
username="administrator",
display_name="Admin",
role="owner",
password_hash="x",
is_active=True,
)
self.member = self.store.create_user_account(
tenant_id=self.tenant_id,
username="alice",
display_name="Alice",
role="member",
password_hash="x",
is_active=True,
)
def tearDown(self) -> None:
self._tmp.cleanup()
def test_weixin_uses_administrator_pool(self) -> None:
uname = resolve_scheduled_viewer_username(
self.store,
tenant_id=self.tenant_id,
user_id=str(self.member["id"]),
channel="weixin",
)
self.assertEqual(uname, "administrator")
def test_admin_chat_uses_job_owner_username(self) -> None:
uname = resolve_scheduled_viewer_username(
self.store,
tenant_id=self.tenant_id,
user_id=str(self.member["id"]),
channel="admin_chat",
)
self.assertEqual(uname, "alice")
def test_enqueue_payload_includes_viewer_username_for_weixin(self) -> None:
job = MagicMock()
job.tenant_id = self.tenant_id
job.id = "job-weixin"
job.next_run_at = "2026-06-26T10:00:00+00:00"
job.delivery_json = '{"weixin":{"enabled":true}}'
job.prompt_text = "stretch"
job.lang = "zh"
job.interaction_mode = "expert"
job.specialist = "generalist"
job.created_by_user_id = str(self.member["id"])
job.schedule_kind = "interval"
job.recipe_json = "{}"
job.source_session_id = ""
job.name = "stretch"
run = MagicMock()
run.id = "run-1"
self.store.scheduled_job_run_create = MagicMock(return_value=run) # type: ignore[method-assign]
self.store.scheduled_job_run_update = MagicMock() # type: ignore[method-assign]
self.store.scheduled_job_reserve_next_run = MagicMock() # type: ignore[method-assign]
captured: dict[str, object] = {}
def _capture_create(**kwargs: object) -> MagicMock:
captured.update(kwargs)
return MagicMock(id="task-1")
self.store.oclaw_task_create = _capture_create # type: ignore[method-assign]
from runtime.scheduler import service as sched_service
from runtime.scheduler.session_resolver import ResolvedSession
resolved = ResolvedSession(
session_id="sess-1",
tenant_id=self.tenant_id,
user_id=str(self.admin["id"]),
channel="weixin",
account_id="weixin-default",
external_chat_id="wx-user-1",
external_user_id="wx-user-1",
is_group=False,
)
original_resolve = sched_service.resolve_scheduled_session
original_worker = sched_service.ensure_worker_started
try:
sched_service.resolve_scheduled_session = MagicMock(return_value=resolved)
sched_service.ensure_worker_started = MagicMock(return_value="worker-1")
enqueue_scheduled_job_run(self.store, job=job, mode="scheduled")
finally:
sched_service.resolve_scheduled_session = original_resolve
sched_service.ensure_worker_started = original_worker
payload = captured.get("payload")
self.assertIsInstance(payload, dict)
assert isinstance(payload, dict)
self.assertEqual(payload.get("viewer_username"), "administrator")
if __name__ == "__main__":
unittest.main()