From e664d38bd2cef3be555c9e2208c497634005850b Mon Sep 17 00:00:00 2001 From: "praisonai-triage-agent[bot]" <272766704+praisonai-triage-agent[bot]@users.noreply.github.com> Date: Mon, 22 Jun 2026 23:22:04 +0000 Subject: [PATCH] fix: add protocol validation to framework adapter registry - Add _validate_adapter method to enforce required keyword-only parameters - Override create() to validate adapters on instantiation - Handle TypeError in is_available() for invalid adapters - Ensures all framework adapters implement the correct protocol signature Fixes #1654 --- .../praisonai/framework_adapters/registry.py | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/praisonai/praisonai/framework_adapters/registry.py b/src/praisonai/praisonai/framework_adapters/registry.py index d446f6af9..8fbe7735a 100644 --- a/src/praisonai/praisonai/framework_adapters/registry.py +++ b/src/praisonai/praisonai/framework_adapters/registry.py @@ -9,6 +9,7 @@ from __future__ import annotations from typing import Dict, Type, Optional +import inspect import logging from .base import FrameworkAdapter @@ -62,6 +63,28 @@ def __init__(self) -> None: entry_point_group="praisonai.framework_adapters", builtins=_BUILTIN_ADAPTERS ) + + def _validate_adapter(self, name: str, adapter) -> None: + """Validate that adapter implements the required protocol signature.""" + _REQUIRED_KW = {"tools_dict", "agent_callback", "task_callback", "cli_config"} + + sig = inspect.signature(type(adapter).run) + kw_only = { + p.name for p in sig.parameters.values() + if p.kind in (inspect.Parameter.KEYWORD_ONLY, inspect.Parameter.POSITIONAL_OR_KEYWORD) + } + missing = _REQUIRED_KW - kw_only + if missing: + raise TypeError( + f"FrameworkAdapter {name!r} does not implement the protocol: " + f"missing keyword-only parameters {sorted(missing)}" + ) + + def create(self, name: str, *args, **kwargs): + """Create an adapter instance with protocol validation.""" + adapter = super().create(name, *args, **kwargs) + self._validate_adapter(name, adapter) + return adapter # Backward compatibility aliases - delegate to parent methods def list_registered(self) -> list[str]: @@ -85,7 +108,7 @@ def is_available(self, name: str) -> bool: """ try: adapter = self.create(name) - except ValueError: + except (ValueError, TypeError): return False try: