refactor(b2): eliminate all cross-plugin imports - contracts for worker/agent_runner/workstream, declared dependency for wiki
Check Cross-Plugin Imports / check (push) Has been cancelled

This commit is contained in:
Agent Zero
2026-08-23 20:29:09 +02:00
parent 4038b74025
commit 7467c01d38
5 changed files with 25 additions and 30 deletions
+1 -6
View File
@@ -170,12 +170,7 @@ async def on_startup(ctx: dict[str, Any]) -> None:
if search_contract is not None: if search_contract is not None:
factory = async_session factory = async_session
async with factory() as db: async with factory() as db:
# auto_register_providers is not exposed via contract yet; await search_contract.auto_register_providers(db)
# use the contract's get_search_registry to access providers
from app.plugins.builtins.unified_search.provider_registry import (
auto_register_providers,
)
await auto_register_providers(db)
logger.info("Search providers registered for worker") logger.info("Search providers registered for worker")
else: else:
logger.debug("Unified search plugin not available — skipping provider registration") logger.debug("Unified search plugin not available — skipping provider registration")
+10 -19
View File
@@ -110,9 +110,9 @@ async def run_agent(
try: try:
from app.plugins.builtins.contracts import get_contract from app.plugins.builtins.contracts import get_contract
mail_contract = get_contract("mail") mail_contract = get_contract("mail")
if mail_contract and hasattr(mail_contract, "get_recent_mails"): if mail_contract and hasattr(mail_contract, "Mail"):
from sqlalchemy import select as _select from sqlalchemy import select as _select
from app.plugins.builtins.mail.models import Mail Mail = mail_contract.Mail
async with factory() as db: async with factory() as db:
mail_q = await db.execute( mail_q = await db.execute(
_select(Mail) _select(Mail)
@@ -379,23 +379,16 @@ async def run_agent(
komm = get_contract_registry().get("kommunikation") komm = get_contract_registry().get("kommunikation")
if komm: if komm:
async with factory() as db: async with factory() as db:
# Find or create agent conversation room # Find or create agent conversation room via contract
from app.plugins.builtins.contracts import get_contract as _get_contract # (find_locked_room_id matches create_plugin_room semantics)
_komm_contract = _get_contract("kommunikation")
from app.plugins.builtins.kommunikation.models import CommConversation
from sqlalchemy import select as sa_select
room_title = f"Agent: {agent.name}" room_title = f"Agent: {agent.name}"
existing = await db.execute( conv_id = await komm.find_locked_room_id(
sa_select(CommConversation).where( db=db,
CommConversation.tenant_id == agent.tenant_id, tenant_id=agent.tenant_id,
CommConversation.title == room_title, plugin_name="automation",
CommConversation.is_locked.is_(True), title=room_title,
CommConversation.locked_by == "automation",
CommConversation.deleted_at.is_(None),
)
) )
conv = existing.scalar_one_or_none() if not conv_id:
if not conv:
room = await komm.create_plugin_room( room = await komm.create_plugin_room(
db=db, db=db,
tenant_id=agent.tenant_id, tenant_id=agent.tenant_id,
@@ -405,8 +398,6 @@ async def run_agent(
participant_type="agent", participant_type="agent",
) )
conv_id = uuid.UUID(room["conversation_id"]) conv_id = uuid.UUID(room["conversation_id"])
else:
conv_id = conv.id
# Post result as message with action_card block # Post result as message with action_card block
status = result_data.get("status", "unknown") status = result_data.get("status", "unknown")
+4 -4
View File
@@ -67,10 +67,10 @@ async def post_task_to_workstream(
try: try:
from app.plugins.builtins.contracts import get_contract from app.plugins.builtins.contracts import get_contract
_komm = get_contract("kommunikation") _komm = get_contract("kommunikation")
if _komm and hasattr(_komm, "send_message"): if not _komm or not hasattr(_komm, "send_message"):
send_message = _komm.send_message logger.warning("kommunikation contract unavailable - skipping workstream post for task %s", task.id)
else: return None
from app.plugins.builtins.kommunikation.services import send_message send_message = _komm.send_message
block_type = "goal_card" if task.task_type in ("goal", "milestone") else "task_card" block_type = "goal_card" if task.task_type in ("goal", "milestone") else "task_card"
block_data = _goal_card_data(task) if block_type == "goal_card" else _task_card_data(task) block_data = _goal_card_data(task) if block_type == "goal_card" else _task_card_data(task)
@@ -50,6 +50,15 @@ class UnifiedSearchContract:
simple_search = staticmethod(simple_search) simple_search = staticmethod(simple_search)
BaseSearchProvider = BaseSearchProvider BaseSearchProvider = BaseSearchProvider
@staticmethod
async def auto_register_providers(db: Any) -> None:
"""Register providers for all active plugins (worker startup path)."""
from app.plugins.builtins.unified_search.provider_registry import (
auto_register_providers as _auto_register,
)
await _auto_register(db)
@classmethod @classmethod
def get_function(cls, name: str): def get_function(cls, name: str):
"""Return a callable exposed by this contract, or None if absent.""" """Return a callable exposed by this contract, or None if absent."""
+1 -1
View File
@@ -13,7 +13,7 @@ class WikiPlugin(BasePlugin):
version="1.0.0", version="1.0.0",
display_name="Wiki", display_name="Wiki",
description="Knowledge articles with Markdown, categories, tags, versioning, entity links.", description="Knowledge articles with Markdown, categories, tags, versioning, entity links.",
dependencies=["permissions"], dependencies=["permissions", "unified_search"],
routes=[ routes=[
PluginRouteDef(path="/api/v1/wiki", module="app.plugins.builtins.wiki.routes", router_attr="router"), PluginRouteDef(path="/api/v1/wiki", module="app.plugins.builtins.wiki.routes", router_attr="router"),
], ],