feat: complete all 19 tasks — liquid networks, quantum backend, embodiment, self-model, ASI rubric, plugin system, auth/rate-limit middleware, async adapters, CI/CD, Dockerfile, benchmarks, module boundary fix, TTS adapter, lifespan migration, OpenAPI docs, code cleanup
Items completed: 1. Merged PR #2 (starlette/httpx deps) 2. Fixed async race condition in multimodal_ui.py 3. Wired TTSAdapter (ElevenLabs, Azure) in API routes 4. Moved super_big_brain.py from core/ to reasoning/ (backward compat shim) 5. Added API authentication middleware (Bearer token via FUSIONAGI_API_KEY) 6. Added async adapter interface (acomplete/acomplete_structured) 7. Migrated FastAPI on_event to lifespan (fixes 20 deprecation warnings) 8. Liquid Neural Networks (continuous-time adaptive weights) 9. Quantum-AI Hybrid compute backend (simulator + optimization) 10. Embodied Intelligence / Robotics bridge (actuator + sensor protocols) 11. Consciousness Engineering (formal self-model with introspection) 12. ASI Scoring Rubric (C/A/L/N/R self-assessment harness) 13. GPU integration tests for TensorFlow backend 14. Multi-stage production Dockerfile 15. Gitea CI/CD pipeline (lint, test matrix, Docker build) 16. API rate limiting middleware (per-IP sliding window) 17. OpenAPI docs cleanup (auth + rate limiting descriptions) 18. Benchmarking suite (decomposition, multi-path, recomposition, e2e) 19. Plugin system (head registry for custom heads) 427 tests passing, 0 ruff errors, 0 mypy errors. Co-Authored-By: Nakamoto, S <defi@defi-oracle.io>
This commit is contained in:
306
fusionagi/agents/head_registry.py
Normal file
306
fusionagi/agents/head_registry.py
Normal file
@@ -0,0 +1,306 @@
|
||||
"""Plugin system — head registry for custom heads.
|
||||
|
||||
Provides a registry-based architecture for dynamically registering,
|
||||
discovering, and creating head agents. Replaces the hardcoded head
|
||||
creation in ``agents/heads/__init__.py`` with an extensible system.
|
||||
|
||||
Usage:
|
||||
|
||||
from fusionagi.agents.head_registry import HeadRegistry
|
||||
|
||||
registry = HeadRegistry()
|
||||
|
||||
# Built-in heads are pre-registered
|
||||
head = registry.create("logic")
|
||||
|
||||
# Register a custom head
|
||||
@registry.register_factory("my_domain")
|
||||
def create_my_head(adapter, **kwargs):
|
||||
return HeadAgent(head_id=HeadId.LOGIC, role="My Domain", ...)
|
||||
|
||||
# Discover all available heads
|
||||
registry.list_heads()
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from typing import Any, Callable
|
||||
|
||||
from fusionagi._logger import logger
|
||||
from fusionagi.adapters.base import LLMAdapter
|
||||
from fusionagi.agents.head_agent import HeadAgent
|
||||
from fusionagi.prompts.heads import get_head_prompt
|
||||
from fusionagi.reasoning.native import NativeReasoningProvider
|
||||
from fusionagi.schemas.head import HeadId
|
||||
|
||||
|
||||
@dataclass
|
||||
class HeadSpec:
|
||||
"""Specification for a registered head type."""
|
||||
|
||||
head_id: str
|
||||
role: str
|
||||
objective: str
|
||||
factory: Callable[..., HeadAgent]
|
||||
description: str = ""
|
||||
tags: list[str] = field(default_factory=list)
|
||||
builtin: bool = True
|
||||
|
||||
|
||||
class HeadRegistry:
|
||||
"""Extensible registry for head agent types.
|
||||
|
||||
Pre-registers all 11 built-in Dvādaśa content heads on creation.
|
||||
Custom heads can be added via ``register()`` or ``register_factory()``.
|
||||
"""
|
||||
|
||||
def __init__(self, *, auto_register_builtins: bool = True) -> None:
|
||||
self._specs: dict[str, HeadSpec] = {}
|
||||
if auto_register_builtins:
|
||||
self._register_builtins()
|
||||
|
||||
def _register_builtins(self) -> None:
|
||||
"""Register all built-in Dvādaśa content heads."""
|
||||
role_map: dict[HeadId, tuple[str, str]] = {
|
||||
HeadId.LOGIC: ("Logic", "Correctness, contradictions, formal checks"),
|
||||
HeadId.RESEARCH: ("Research", "Retrieval, source quality, citations"),
|
||||
HeadId.SYSTEMS: ("Systems", "Architecture, dependencies, scalability"),
|
||||
HeadId.STRATEGY: ("Strategy", "Roadmap, prioritization, tradeoffs"),
|
||||
HeadId.PRODUCT: ("Product/UX", "Interaction design, user flows"),
|
||||
HeadId.SECURITY: ("Security", "Threats, auth, secrets, abuse vectors"),
|
||||
HeadId.SAFETY: ("Safety/Ethics", "Policy alignment, harmful content prevention"),
|
||||
HeadId.RELIABILITY: ("Reliability", "SLOs, failover, load testing, observability"),
|
||||
HeadId.COST: ("Cost/Performance", "Token budgets, caching, model routing"),
|
||||
HeadId.DATA: ("Data/Memory", "Schemas, privacy, retention, personalization"),
|
||||
HeadId.DEVEX: ("DevEx", "CI/CD, testing strategy, local tooling"),
|
||||
}
|
||||
|
||||
for head_id, (role, objective) in role_map.items():
|
||||
self._register_builtin_head(head_id, role, objective)
|
||||
|
||||
def _register_builtin_head(
|
||||
self, head_id: HeadId, role: str, objective: str
|
||||
) -> None:
|
||||
"""Register a single built-in head."""
|
||||
|
||||
def factory(
|
||||
adapter: LLMAdapter | None = None,
|
||||
tool_permissions: list[str] | None = None,
|
||||
reasoning_provider: NativeReasoningProvider | None = None,
|
||||
use_native_reasoning: bool = True,
|
||||
_hid: HeadId = head_id,
|
||||
_role: str = role,
|
||||
_obj: str = objective,
|
||||
**kwargs: Any,
|
||||
) -> HeadAgent:
|
||||
provider = reasoning_provider
|
||||
if provider is None and use_native_reasoning and adapter is None:
|
||||
provider = NativeReasoningProvider()
|
||||
|
||||
return HeadAgent(
|
||||
head_id=_hid,
|
||||
role=_role,
|
||||
objective=_obj,
|
||||
system_prompt=get_head_prompt(_hid),
|
||||
adapter=adapter,
|
||||
tool_permissions=tool_permissions,
|
||||
reasoning_provider=provider,
|
||||
)
|
||||
|
||||
self._specs[head_id.value] = HeadSpec(
|
||||
head_id=head_id.value,
|
||||
role=role,
|
||||
objective=objective,
|
||||
factory=factory,
|
||||
description=f"Built-in {role} head",
|
||||
tags=["builtin", "dvadasa"],
|
||||
builtin=True,
|
||||
)
|
||||
|
||||
def register(
|
||||
self,
|
||||
head_id: str,
|
||||
role: str,
|
||||
objective: str,
|
||||
factory: Callable[..., HeadAgent],
|
||||
*,
|
||||
description: str = "",
|
||||
tags: list[str] | None = None,
|
||||
) -> None:
|
||||
"""Register a custom head type.
|
||||
|
||||
Args:
|
||||
head_id: Unique identifier for the head.
|
||||
role: Head's role name.
|
||||
objective: What the head does.
|
||||
factory: Callable that creates a HeadAgent.
|
||||
description: Human-readable description.
|
||||
tags: Optional tags for discovery.
|
||||
"""
|
||||
if head_id in self._specs:
|
||||
logger.warning(
|
||||
"Overwriting existing head registration",
|
||||
extra={"head_id": head_id},
|
||||
)
|
||||
|
||||
self._specs[head_id] = HeadSpec(
|
||||
head_id=head_id,
|
||||
role=role,
|
||||
objective=objective,
|
||||
factory=factory,
|
||||
description=description,
|
||||
tags=tags or [],
|
||||
builtin=False,
|
||||
)
|
||||
logger.info("Custom head registered", extra={"head_id": head_id, "role": role})
|
||||
|
||||
def register_factory(
|
||||
self,
|
||||
head_id: str,
|
||||
*,
|
||||
role: str = "",
|
||||
objective: str = "",
|
||||
description: str = "",
|
||||
tags: list[str] | None = None,
|
||||
) -> Callable[[Callable[..., HeadAgent]], Callable[..., HeadAgent]]:
|
||||
"""Decorator to register a head factory function.
|
||||
|
||||
Args:
|
||||
head_id: Unique identifier.
|
||||
role: Head's role name.
|
||||
objective: What the head does.
|
||||
description: Human-readable description.
|
||||
tags: Optional tags.
|
||||
|
||||
Returns:
|
||||
Decorator function.
|
||||
"""
|
||||
|
||||
def decorator(fn: Callable[..., HeadAgent]) -> Callable[..., HeadAgent]:
|
||||
self.register(
|
||||
head_id=head_id,
|
||||
role=role or head_id.replace("_", " ").title(),
|
||||
objective=objective or fn.__doc__ or "",
|
||||
factory=fn,
|
||||
description=description,
|
||||
tags=tags,
|
||||
)
|
||||
return fn
|
||||
|
||||
return decorator
|
||||
|
||||
def create(
|
||||
self,
|
||||
head_id: str,
|
||||
adapter: LLMAdapter | None = None,
|
||||
**kwargs: Any,
|
||||
) -> HeadAgent:
|
||||
"""Create a head agent by ID.
|
||||
|
||||
Args:
|
||||
head_id: Registered head identifier.
|
||||
adapter: Optional LLM adapter.
|
||||
**kwargs: Additional arguments passed to factory.
|
||||
|
||||
Returns:
|
||||
Created HeadAgent.
|
||||
|
||||
Raises:
|
||||
KeyError: If head_id is not registered.
|
||||
"""
|
||||
if head_id not in self._specs:
|
||||
raise KeyError(
|
||||
f"Head '{head_id}' not registered. "
|
||||
f"Available: {', '.join(sorted(self._specs.keys()))}"
|
||||
)
|
||||
spec = self._specs[head_id]
|
||||
return spec.factory(adapter=adapter, **kwargs)
|
||||
|
||||
def create_all(
|
||||
self,
|
||||
adapter: LLMAdapter | None = None,
|
||||
*,
|
||||
include_tags: list[str] | None = None,
|
||||
exclude_tags: list[str] | None = None,
|
||||
**kwargs: Any,
|
||||
) -> dict[str, HeadAgent]:
|
||||
"""Create all registered heads (optionally filtered by tags).
|
||||
|
||||
Args:
|
||||
adapter: Optional LLM adapter.
|
||||
include_tags: Only create heads matching these tags.
|
||||
exclude_tags: Skip heads matching these tags.
|
||||
**kwargs: Additional arguments.
|
||||
|
||||
Returns:
|
||||
Dict of head_id -> HeadAgent.
|
||||
"""
|
||||
heads: dict[str, HeadAgent] = {}
|
||||
for hid, spec in self._specs.items():
|
||||
if include_tags and not any(t in spec.tags for t in include_tags):
|
||||
continue
|
||||
if exclude_tags and any(t in spec.tags for t in exclude_tags):
|
||||
continue
|
||||
heads[hid] = spec.factory(adapter=adapter, **kwargs)
|
||||
return heads
|
||||
|
||||
def list_heads(self) -> list[dict[str, Any]]:
|
||||
"""List all registered heads.
|
||||
|
||||
Returns:
|
||||
List of head specifications.
|
||||
"""
|
||||
return [
|
||||
{
|
||||
"head_id": spec.head_id,
|
||||
"role": spec.role,
|
||||
"objective": spec.objective,
|
||||
"description": spec.description,
|
||||
"tags": spec.tags,
|
||||
"builtin": spec.builtin,
|
||||
}
|
||||
for spec in self._specs.values()
|
||||
]
|
||||
|
||||
def get_spec(self, head_id: str) -> HeadSpec | None:
|
||||
"""Get the spec for a registered head."""
|
||||
return self._specs.get(head_id)
|
||||
|
||||
def unregister(self, head_id: str) -> bool:
|
||||
"""Remove a head registration.
|
||||
|
||||
Args:
|
||||
head_id: Head to remove.
|
||||
|
||||
Returns:
|
||||
True if removed, False if not found.
|
||||
"""
|
||||
if head_id in self._specs:
|
||||
del self._specs[head_id]
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def registered_count(self) -> int:
|
||||
"""Number of registered heads."""
|
||||
return len(self._specs)
|
||||
|
||||
|
||||
# Global default registry
|
||||
_default_registry: HeadRegistry | None = None
|
||||
|
||||
|
||||
def get_default_registry() -> HeadRegistry:
|
||||
"""Get or create the default global head registry."""
|
||||
global _default_registry # noqa: PLW0603
|
||||
if _default_registry is None:
|
||||
_default_registry = HeadRegistry()
|
||||
return _default_registry
|
||||
|
||||
|
||||
__all__ = [
|
||||
"HeadRegistry",
|
||||
"HeadSpec",
|
||||
"get_default_registry",
|
||||
]
|
||||
Reference in New Issue
Block a user