Initial commit
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
from dataclasses import dataclass, field
|
||||
from types import SimpleNamespace
|
||||
|
||||
import aiosqlite
|
||||
|
||||
from opc.core.config import RoleConfig
|
||||
from opc.plugins.office_ui.agent_store import AgentStore
|
||||
|
||||
|
||||
@dataclass
|
||||
class _Role:
|
||||
name: str
|
||||
responsibility: str = ""
|
||||
tools: list[str] = field(default_factory=list)
|
||||
|
||||
|
||||
class _OrgEngine:
|
||||
def get_agent(self, role_id: str) -> _Role | None:
|
||||
roles = {
|
||||
"coordinator": _Role(
|
||||
name="Custom Leader",
|
||||
responsibility="Lead the custom team.",
|
||||
tools=["send_dm", "todo_write"],
|
||||
),
|
||||
"executor": _Role(
|
||||
name="Executor",
|
||||
responsibility="Execute assigned work.",
|
||||
tools=["shell_exec"],
|
||||
),
|
||||
}
|
||||
return roles.get(role_id)
|
||||
|
||||
|
||||
class _PresetOrgEngine(_OrgEngine):
|
||||
def __init__(self) -> None:
|
||||
self.config = SimpleNamespace(
|
||||
org=SimpleNamespace(
|
||||
roles=[
|
||||
RoleConfig(
|
||||
id="ceo",
|
||||
name="Configured CEO",
|
||||
responsibility="Configured leader",
|
||||
tools=["file_read", "todo_write"],
|
||||
)
|
||||
]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
class AgentStoreCustomModeTests(unittest.IsolatedAsyncioTestCase):
|
||||
async def asyncSetUp(self) -> None:
|
||||
self.db = await aiosqlite.connect(":memory:")
|
||||
self.store = AgentStore(self.db)
|
||||
await self.store.initialize()
|
||||
self.org_engine = _OrgEngine()
|
||||
|
||||
async def asyncTearDown(self) -> None:
|
||||
await self.db.close()
|
||||
|
||||
async def test_custom_mode_without_shadow_resets_to_single_starter(self) -> None:
|
||||
preset_agents = await self.store.load_preset("corporate", self.org_engine)
|
||||
self.assertGreater(len(preset_agents), 1)
|
||||
self.assertTrue(any(agent["opc_role_id"] == "ceo" for agent in preset_agents))
|
||||
|
||||
custom_agents = await self.store.load_preset("custom", self.org_engine)
|
||||
|
||||
self.assertEqual(len(custom_agents), 1)
|
||||
self.assertEqual(custom_agents[0]["agent_id"], "custom-leader")
|
||||
self.assertEqual(custom_agents[0]["opc_role_id"], "coordinator")
|
||||
self.assertFalse(any(agent["opc_role_id"] == "ceo" for agent in custom_agents))
|
||||
|
||||
async def test_custom_mode_restores_saved_custom_team(self) -> None:
|
||||
starter_agents = await self.store.load_preset("custom", self.org_engine)
|
||||
self.assertEqual([agent["agent_id"] for agent in starter_agents], ["custom-leader"])
|
||||
|
||||
await self.store.create_agent(
|
||||
name="Planner",
|
||||
opc_role_id="planner",
|
||||
office_id="office-1",
|
||||
description="Plans the work.",
|
||||
specialties=["planning"],
|
||||
)
|
||||
await self.store.sync_custom_shadow()
|
||||
|
||||
await self.store.load_preset("corporate", self.org_engine)
|
||||
restored_agents = await self.store.load_preset("custom", self.org_engine)
|
||||
restored_role_ids = {agent["opc_role_id"] for agent in restored_agents}
|
||||
|
||||
self.assertEqual(restored_role_ids, {"coordinator", "planner"})
|
||||
self.assertFalse(any(agent["opc_role_id"] == "ceo" for agent in restored_agents))
|
||||
|
||||
async def test_builtin_preset_uses_configured_role_tool_overrides(self) -> None:
|
||||
preset_agents = await self.store.load_preset("corporate", _PresetOrgEngine())
|
||||
ceo = next(agent for agent in preset_agents if agent["opc_role_id"] == "ceo")
|
||||
|
||||
self.assertEqual(ceo["name"], "Configured CEO")
|
||||
self.assertEqual(set(ceo["specialties"]), {"file_read", "todo_write"})
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,228 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from types import SimpleNamespace
|
||||
import unittest
|
||||
|
||||
from opc.core.models import (
|
||||
DelegationCell,
|
||||
DelegationRun,
|
||||
DelegationRoleSession,
|
||||
DelegationWorkItem,
|
||||
Phase,
|
||||
)
|
||||
from opc.plugins.office_ui.ws_handler import WSHandler
|
||||
|
||||
|
||||
class DummyStore:
|
||||
is_ready = True
|
||||
|
||||
async def list_open_delegation_runs(self, project_id: str): # noqa: ARG002
|
||||
return [
|
||||
DelegationRun(
|
||||
run_id="run-1",
|
||||
project_id=project_id,
|
||||
status="running",
|
||||
lifecycle_status="active",
|
||||
current_revision=3,
|
||||
latest_deliverable_summary="Latest delivery snapshot",
|
||||
recovery_pointer={"status": "warm"},
|
||||
)
|
||||
]
|
||||
|
||||
async def list_delegation_cells(self, run_id: str):
|
||||
return [
|
||||
DelegationCell(
|
||||
cell_id="cell-1",
|
||||
run_id=run_id,
|
||||
manager_role_id="role-1",
|
||||
member_role_ids=["role-1"],
|
||||
status="running",
|
||||
metadata={"is_final_decider_cell": True},
|
||||
)
|
||||
]
|
||||
|
||||
async def list_delegation_role_sessions(self, run_id: str):
|
||||
return [
|
||||
DelegationRoleSession(
|
||||
role_session_id="seat-1",
|
||||
run_id=run_id,
|
||||
role_id="role-1",
|
||||
employee_id="emp-1",
|
||||
focused_work_item_id="wi-1",
|
||||
background_work_item_ids=["wi-2"],
|
||||
manager_role_ids=["role-manager"],
|
||||
status="active",
|
||||
)
|
||||
]
|
||||
|
||||
async def list_delegation_work_items(self, run_id: str):
|
||||
return [
|
||||
DelegationWorkItem(
|
||||
work_item_id="wi-1",
|
||||
run_id=run_id,
|
||||
cell_id="cell-1",
|
||||
role_id="role-1",
|
||||
title="Primary work item",
|
||||
kind="execute",
|
||||
phase=Phase.RUNNING,
|
||||
batch_id="batch-1",
|
||||
batch_index=0,
|
||||
projection_id="projection-legacy",
|
||||
metadata={
|
||||
"adaptive": {
|
||||
"normalized_state": "waiting_for_gate",
|
||||
"blocked_reason": "Waiting for required signals: implementation_ready",
|
||||
}
|
||||
},
|
||||
),
|
||||
DelegationWorkItem(
|
||||
work_item_id="wi-2",
|
||||
run_id=run_id,
|
||||
cell_id="cell-1",
|
||||
role_id="role-1",
|
||||
title="Follow-up work item",
|
||||
kind="execute",
|
||||
phase=Phase.APPROVED,
|
||||
batch_id="batch-1",
|
||||
batch_index=1,
|
||||
projection_id="projection-legacy",
|
||||
),
|
||||
]
|
||||
|
||||
async def list_team_instances(self, run_id: str): # noqa: ARG002
|
||||
return []
|
||||
|
||||
async def list_seat_states(self, run_id: str): # noqa: ARG002
|
||||
return []
|
||||
|
||||
async def get_session_links(self, session_id: str, limit: int = 50): # noqa: ARG002
|
||||
return []
|
||||
|
||||
|
||||
class DummyOrg:
|
||||
def list_agents(self):
|
||||
return [
|
||||
SimpleNamespace(
|
||||
role_id="role-1",
|
||||
name="Role One",
|
||||
responsibility="Do the thing",
|
||||
status="active",
|
||||
reports_to="owner",
|
||||
icon=None,
|
||||
can_spawn=[],
|
||||
tools=["tool-a"],
|
||||
runtime_policy={"execution_strategy": "auto"},
|
||||
preferred_external_agent=None,
|
||||
prompt_refs=[],
|
||||
)
|
||||
]
|
||||
|
||||
def list_employees(self):
|
||||
return [
|
||||
SimpleNamespace(
|
||||
employee_id="emp-1",
|
||||
name="Employee One",
|
||||
role_id="role-1",
|
||||
category="general",
|
||||
domains=["ops"],
|
||||
seniority="senior",
|
||||
status="active",
|
||||
tags=["tag-1"],
|
||||
skill_refs=["skill-1"],
|
||||
)
|
||||
]
|
||||
|
||||
def get_company_profile(self):
|
||||
return "corporate"
|
||||
|
||||
def get_execution_model(self):
|
||||
return "actor_runtime"
|
||||
|
||||
def get_final_decider_role_id(self, strict: bool = False): # noqa: ARG002
|
||||
return "role-1"
|
||||
|
||||
def get_top_level_role_ids(self):
|
||||
return ["role-1"]
|
||||
|
||||
def current_org_version(self):
|
||||
return 9
|
||||
|
||||
def current_runtime_topology_version(self):
|
||||
return 4
|
||||
|
||||
def get_runtime_policy(self, profile: str): # noqa: ARG002
|
||||
return {"parallel": {"auto_dispatch": True}}
|
||||
|
||||
|
||||
class DummyChannelManager:
|
||||
def get_all_statuses(self):
|
||||
return [
|
||||
{
|
||||
"name": "slack",
|
||||
"enabled": True,
|
||||
"running": True,
|
||||
"configured": True,
|
||||
"available": True,
|
||||
"ready": True,
|
||||
"last_error": None,
|
||||
"delivery_mode": "push",
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
class DummyPackage:
|
||||
def model_dump(self):
|
||||
return {"package_id": "pkg-1", "name": "Package 1"}
|
||||
|
||||
|
||||
class DummyEngine:
|
||||
def __init__(self):
|
||||
self.project_id = "project-1"
|
||||
self.org_engine = DummyOrg()
|
||||
self.store = DummyStore()
|
||||
self.channel_manager = DummyChannelManager()
|
||||
self.config = SimpleNamespace(
|
||||
org=SimpleNamespace(installed_packages=[DummyPackage()]),
|
||||
save=lambda: None,
|
||||
)
|
||||
self.on_company_runtime_children = None
|
||||
self.on_escalation = None
|
||||
self.escalation = None
|
||||
|
||||
|
||||
class DummyStoreLike:
|
||||
pass
|
||||
|
||||
|
||||
class TestOrgInfoPayload(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_org_info_payload_exposes_modern_runtime_fields_only(self) -> None:
|
||||
handler = WSHandler(DummyEngine(), DummyStoreLike(), DummyStoreLike(), DummyStoreLike())
|
||||
|
||||
payload = await handler._build_org_info_payload()
|
||||
|
||||
self.assertNotIn("active_cells", payload)
|
||||
self.assertNotIn("role_sessions", payload)
|
||||
self.assertNotIn("active_work_items", payload)
|
||||
self.assertNotIn("run_frontier_summary", payload)
|
||||
self.assertNotIn("legacy_snapshot", payload)
|
||||
self.assertNotIn("execution_model", payload)
|
||||
self.assertEqual(payload["runtime_teams"][0]["cell_id"], "cell-1")
|
||||
self.assertEqual(payload["runtime_seats"][0]["role_session_id"], "seat-1")
|
||||
self.assertEqual(payload["project_run"]["run_id"], "run-1")
|
||||
self.assertEqual(payload["project_run"]["current_revision"], 3)
|
||||
self.assertEqual(payload["project_run"]["latest_deliverable_summary"], "Latest delivery snapshot")
|
||||
legacy_prefix = "work" + "flow_"
|
||||
self.assertNotIn(legacy_prefix + "definition_mode", payload)
|
||||
self.assertNotIn(legacy_prefix + "projection_source", payload)
|
||||
self.assertNotIn("work_item_projection_titles", payload)
|
||||
self.assertEqual(payload["company_profile"], "corporate")
|
||||
self.assertEqual(payload["runtime_topology_version"], 4)
|
||||
self.assertEqual(payload["runtime_policy"]["parallel"]["auto_dispatch"], True)
|
||||
|
||||
self.assertEqual(payload["frontier"]["status"], "running")
|
||||
self.assertEqual(payload["work_items"][0]["batch_id"], "batch-1")
|
||||
self.assertEqual(payload["work_items"][0]["work_item_projection_id"], "projection-legacy")
|
||||
self.assertNotIn("projection_id", payload["work_items"][0])
|
||||
self.assertEqual(payload["work_items"][0]["adaptive"]["normalized_state"], "waiting_for_gate")
|
||||
self.assertEqual(payload["channels"][0]["name"], "slack")
|
||||
self.assertEqual(payload["installed_packages"][0]["package_id"], "pkg-1")
|
||||
@@ -0,0 +1,53 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import PurePosixPath, PureWindowsPath
|
||||
|
||||
from opc.plugins.office_ui.server import _is_under_path
|
||||
|
||||
|
||||
def test_is_under_path_accepts_platform_child_paths() -> None:
|
||||
cases = [
|
||||
(
|
||||
PureWindowsPath(r"C:\work\OpenOPC\opc\plugins\office_ui\frontend_dist\assets\index.js"),
|
||||
PureWindowsPath(r"C:\work\OpenOPC\opc\plugins\office_ui\frontend_dist\assets"),
|
||||
),
|
||||
(
|
||||
PurePosixPath("/work/OpenOPC/opc/plugins/office_ui/frontend_dist/assets/index.js"),
|
||||
PurePosixPath("/work/OpenOPC/opc/plugins/office_ui/frontend_dist/assets"),
|
||||
),
|
||||
]
|
||||
|
||||
for child, base in cases:
|
||||
assert _is_under_path(child, base)
|
||||
|
||||
|
||||
def test_is_under_path_rejects_sibling_prefixes() -> None:
|
||||
cases = [
|
||||
(
|
||||
PureWindowsPath(r"C:\work\OpenOPC\opc\plugins\office_ui\frontend_dist\assets-old\index.js"),
|
||||
PureWindowsPath(r"C:\work\OpenOPC\opc\plugins\office_ui\frontend_dist\assets"),
|
||||
),
|
||||
(
|
||||
PurePosixPath("/work/OpenOPC/opc/plugins/office_ui/frontend_dist/assets-old/index.js"),
|
||||
PurePosixPath("/work/OpenOPC/opc/plugins/office_ui/frontend_dist/assets"),
|
||||
),
|
||||
]
|
||||
|
||||
for child, base in cases:
|
||||
assert not _is_under_path(child, base)
|
||||
|
||||
|
||||
def test_is_under_path_rejects_traversal_after_resolution() -> None:
|
||||
cases = [
|
||||
(
|
||||
PureWindowsPath(r"C:\work\OpenOPC\opc\plugins\office_ui\frontend_dist\index.html"),
|
||||
PureWindowsPath(r"C:\work\OpenOPC\opc\plugins\office_ui\frontend_dist\assets"),
|
||||
),
|
||||
(
|
||||
PurePosixPath("/work/OpenOPC/opc/plugins/office_ui/frontend_dist/index.html"),
|
||||
PurePosixPath("/work/OpenOPC/opc/plugins/office_ui/frontend_dist/assets"),
|
||||
),
|
||||
]
|
||||
|
||||
for escaped, base in cases:
|
||||
assert not _is_under_path(escaped, base)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,120 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from types import SimpleNamespace
|
||||
|
||||
from opc.plugins.office_ui.snapshot_builder import _build_session_work_item_log
|
||||
|
||||
|
||||
def _task(
|
||||
task_id: str,
|
||||
*,
|
||||
title: str,
|
||||
assigned_to: str = "",
|
||||
metadata: dict | None = None,
|
||||
):
|
||||
return SimpleNamespace(
|
||||
id=task_id,
|
||||
title=title,
|
||||
assigned_to=assigned_to,
|
||||
metadata=metadata or {},
|
||||
)
|
||||
|
||||
|
||||
def test_build_session_work_item_log_aggregates_child_work_item_progress_for_primary_session() -> None:
|
||||
parent = _task("parent-task", title="Primary Session")
|
||||
child_a = _task(
|
||||
"child-a",
|
||||
title="CEO Intake",
|
||||
assigned_to="ceo",
|
||||
metadata={"work_item_projection_id": "ceo__intake", "work_item_role_name": "CEO"},
|
||||
)
|
||||
child_b = _task(
|
||||
"child-b",
|
||||
title="CTO Delegation",
|
||||
assigned_to="cto",
|
||||
metadata={"work_item_projection_id": "cto__delegate", "work_item_role_name": "CTO"},
|
||||
)
|
||||
|
||||
work_item_log = _build_session_work_item_log(
|
||||
parent,
|
||||
task_meta={},
|
||||
child_tasks=[child_b, child_a],
|
||||
task_meta_map={
|
||||
"parent-task": {},
|
||||
"child-a": dict(child_a.metadata),
|
||||
"child-b": dict(child_b.metadata),
|
||||
},
|
||||
progress_by_task={
|
||||
"child-a": [
|
||||
{"timestamp": 10.0, "type": "work_item_started", "detail": "starting CEO Intake"},
|
||||
{"timestamp": 12.0, "type": "gate_approved", "detail": "completed"},
|
||||
],
|
||||
"child-b": [
|
||||
{"timestamp": 11.0, "type": "work_item_started", "detail": "starting CTO Delegation"},
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
assert [entry["execution_turn_id"] for entry in work_item_log] == ["child-a", "child-b", "child-a"]
|
||||
assert [entry["work_item_projection_id"] for entry in work_item_log] == ["ceo__intake", "cto__delegate", "ceo__intake"]
|
||||
assert [entry["work_item_projection_title"] for entry in work_item_log] == ["CEO", "CTO", "CEO"]
|
||||
assert all("projection_id" not in entry for entry in work_item_log)
|
||||
assert all("legacy_title" not in entry for entry in work_item_log)
|
||||
assert work_item_log[0]["role_name"] == "CEO"
|
||||
assert work_item_log[1]["role_name"] == "CTO"
|
||||
|
||||
|
||||
def test_build_session_work_item_log_keeps_child_session_projection_identity() -> None:
|
||||
child = _task(
|
||||
"child-task",
|
||||
title="CEO Intake",
|
||||
assigned_to="ceo",
|
||||
metadata={"work_item_projection_id": "ceo__intake", "work_item_role_name": "CEO"},
|
||||
)
|
||||
|
||||
work_item_log = _build_session_work_item_log(
|
||||
child,
|
||||
task_meta=dict(child.metadata),
|
||||
child_tasks=[],
|
||||
task_meta_map={"child-task": dict(child.metadata)},
|
||||
progress_by_task={
|
||||
"child-task": [
|
||||
{"timestamp": 20.0, "type": "work_item_started", "detail": "starting CEO Intake"},
|
||||
{"timestamp": 21.0, "type": "awaiting_manager_review", "detail": "awaiting manager review"},
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
assert len(work_item_log) == 2
|
||||
assert all(entry["execution_turn_id"] == "child-task" for entry in work_item_log)
|
||||
assert all(entry["work_item_projection_id"] == "ceo__intake" for entry in work_item_log)
|
||||
assert all("projection_id" not in entry for entry in work_item_log)
|
||||
assert all("legacy_title" not in entry for entry in work_item_log)
|
||||
assert all(entry["role_name"] == "CEO" for entry in work_item_log)
|
||||
|
||||
|
||||
def test_build_session_work_item_log_uses_projection_metadata_for_entries_without_identity() -> None:
|
||||
child = _task("projection-child", title="Projection Work Item", assigned_to="cto")
|
||||
|
||||
work_item_log = _build_session_work_item_log(
|
||||
child,
|
||||
task_meta={"work_item_projection_id": "projection_item"},
|
||||
child_tasks=[],
|
||||
task_meta_map={"projection-child": {"work_item_projection_id": "projection_item"}},
|
||||
progress_by_task={
|
||||
"projection-child": [
|
||||
{
|
||||
"timestamp": 30.0,
|
||||
"type": "work_item_started",
|
||||
"detail": "projection progress",
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
|
||||
assert len(work_item_log) == 1
|
||||
assert work_item_log[0]["work_item_projection_id"] == "projection_item"
|
||||
assert work_item_log[0]["work_item_projection_title"] == "CTO"
|
||||
assert work_item_log[0]["execution_turn_id"] == "projection-child"
|
||||
assert "projection_id" not in work_item_log[0]
|
||||
assert "legacy_title" not in work_item_log[0]
|
||||
Reference in New Issue
Block a user