feat(board): introduce new board agent templates and restructure existing files
This commit is contained in:
@@ -10,6 +10,7 @@ from uuid import UUID, uuid4
|
||||
import pytest
|
||||
|
||||
import app.services.openclaw.provisioning_db as agent_service
|
||||
from app.models.approvals import Approval
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -106,7 +107,11 @@ async def test_delete_gateway_main_agent_does_not_require_board_id(
|
||||
called["delete_lifecycle"] += 1
|
||||
return "/tmp/openclaw/workspace-gateway-x"
|
||||
|
||||
updated_models: list[type[object]] = []
|
||||
|
||||
async def _fake_update_where(*_args, **_kwargs) -> None:
|
||||
if len(_args) >= 2 and isinstance(_args[1], type):
|
||||
updated_models.append(_args[1])
|
||||
return None
|
||||
|
||||
monkeypatch.setattr(service, "require_agent_access", _no_access_check)
|
||||
@@ -124,4 +129,5 @@ async def test_delete_gateway_main_agent_does_not_require_board_id(
|
||||
|
||||
assert result.ok is True
|
||||
assert called["delete_lifecycle"] == 1
|
||||
assert Approval in updated_models
|
||||
assert session.deleted and session.deleted[0] == agent
|
||||
|
||||
@@ -10,6 +10,7 @@ import pytest
|
||||
|
||||
import app.services.openclaw.internal.agent_key as agent_key_mod
|
||||
import app.services.openclaw.provisioning as agent_provisioning
|
||||
from app.services.souls_directory import SoulRef
|
||||
from app.services.openclaw.provisioning_db import AgentLifecycleService
|
||||
from app.services.openclaw.shared import GatewayAgentIdentity
|
||||
|
||||
@@ -357,6 +358,68 @@ def test_is_missing_agent_error_matches_gateway_agent_not_found() -> None:
|
||||
)
|
||||
|
||||
|
||||
def test_select_role_soul_ref_prefers_exact_slug() -> None:
|
||||
refs = [
|
||||
SoulRef(handle="team", slug="security"),
|
||||
SoulRef(handle="team", slug="security-auditor"),
|
||||
SoulRef(handle="team", slug="security-auditor-pro"),
|
||||
]
|
||||
|
||||
selected = agent_provisioning._select_role_soul_ref(refs, role="Security Auditor")
|
||||
|
||||
assert selected is not None
|
||||
assert selected.slug == "security-auditor"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_role_soul_markdown_returns_best_effort(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
refs = [SoulRef(handle="team", slug="data-scientist")]
|
||||
|
||||
async def _fake_list_refs() -> list[SoulRef]:
|
||||
return refs
|
||||
|
||||
async def _fake_fetch(*, handle: str, slug: str, client=None) -> str:
|
||||
_ = client
|
||||
assert handle == "team"
|
||||
assert slug == "data-scientist"
|
||||
return "# SOUL.md - Data Scientist"
|
||||
|
||||
monkeypatch.setattr(
|
||||
agent_provisioning.souls_directory,
|
||||
"list_souls_directory_refs",
|
||||
_fake_list_refs,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
agent_provisioning.souls_directory,
|
||||
"fetch_soul_markdown",
|
||||
_fake_fetch,
|
||||
)
|
||||
|
||||
markdown, source_url = await agent_provisioning._resolve_role_soul_markdown("Data Scientist")
|
||||
|
||||
assert markdown == "# SOUL.md - Data Scientist"
|
||||
assert source_url == "https://souls.directory/souls/team/data-scientist"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_resolve_role_soul_markdown_returns_empty_on_directory_error(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
async def _fake_list_refs() -> list[SoulRef]:
|
||||
raise RuntimeError("network down")
|
||||
|
||||
monkeypatch.setattr(
|
||||
agent_provisioning.souls_directory,
|
||||
"list_souls_directory_refs",
|
||||
_fake_list_refs,
|
||||
)
|
||||
|
||||
markdown, source_url = await agent_provisioning._resolve_role_soul_markdown("DevOps Engineer")
|
||||
|
||||
assert markdown == ""
|
||||
assert source_url == ""
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_agent_lifecycle_ignores_missing_gateway_agent(monkeypatch) -> None:
|
||||
class _ControlPlaneStub:
|
||||
|
||||
@@ -101,7 +101,7 @@ async def test_gateway_coordination_nudge_success(monkeypatch: pytest.MonkeyPatc
|
||||
board=board, # type: ignore[arg-type]
|
||||
actor_agent=actor, # type: ignore[arg-type]
|
||||
target_agent_id=str(target.id),
|
||||
message="Please run BOOT.md",
|
||||
message="Please run session startup checklist",
|
||||
correlation_id="nudge-corr-id",
|
||||
)
|
||||
|
||||
@@ -169,7 +169,7 @@ async def test_gateway_coordination_nudge_maps_gateway_error(
|
||||
board=board, # type: ignore[arg-type]
|
||||
actor_agent=actor, # type: ignore[arg-type]
|
||||
target_agent_id=str(target.id),
|
||||
message="Please run BOOT.md",
|
||||
message="Please run session startup checklist",
|
||||
correlation_id="nudge-corr-id",
|
||||
)
|
||||
|
||||
|
||||
@@ -12,9 +12,7 @@ TEMPLATES_DIR = Path(__file__).resolve().parents[1] / "templates"
|
||||
def test_heartbeat_templates_fit_in_injected_context_limit() -> None:
|
||||
"""Heartbeat templates must stay under gateway injected-context truncation limit."""
|
||||
targets = (
|
||||
"HEARTBEAT_LEAD.md",
|
||||
"HEARTBEAT_AGENT.md",
|
||||
"MAIN_HEARTBEAT.md",
|
||||
"BOARD_HEARTBEAT.md.j2",
|
||||
)
|
||||
for name in targets:
|
||||
size = (TEMPLATES_DIR / name).stat().st_size
|
||||
|
||||
Reference in New Issue
Block a user