feat: implement channel runtime connectors

This commit is contained in:
2026-06-03 16:22:44 +08:00
parent ee972441f5
commit c3d84b904a
105 changed files with 15621 additions and 322 deletions

View File

@ -13,6 +13,7 @@ from .schema import (
AuthzConfig,
BackendIdentityConfig,
BeaverConfig,
ChannelConfig,
EmbeddingConfig,
MCPServerConfig,
ProviderConfig,
@ -73,6 +74,7 @@ def load_config(
embedding=_parse_embedding(data),
tools=_parse_tools(data.get("tools")),
authz=_parse_authz(data.get("authz")),
channels=_parse_channels(data.get("channels")),
backend_identity=_parse_backend_identity(data.get("backend_identity") or data.get("backendIdentity")),
config_path=path,
)
@ -196,6 +198,48 @@ def _parse_authz(raw: Any) -> AuthzConfig:
)
def _parse_channels(raw: Any) -> dict[str, ChannelConfig]:
channels: dict[str, ChannelConfig] = {}
for channel_id, payload in _as_dict(raw).items():
cleaned_id = str(channel_id).strip()
if not cleaned_id:
continue
channels[cleaned_id] = _parse_channel_config(payload)
return channels
def _parse_channel_config(payload: Any) -> ChannelConfig:
data = _as_dict(payload)
return ChannelConfig(
enabled=_bool(data.get("enabled"), default=False),
kind=_string(data.get("kind")) or "",
mode=_string(data.get("mode")) or "webhook",
account_id=_string(data.get("accountId") or data.get("account_id")) or "",
display_name=_string(data.get("displayName") or data.get("display_name")) or "",
config=_normalize_config_map(data.get("config")),
secrets=_string_dict(data.get("secrets")),
)
def _normalize_config_map(value: Any) -> dict[str, Any]:
if not isinstance(value, dict):
return {}
return {
_camel_to_snake_key(str(key)): item
for key, item in value.items()
if str(key).strip()
}
def _camel_to_snake_key(value: str) -> str:
result: list[str] = []
for char in value:
if char.isupper() and result:
result.append("_")
result.append(char.lower())
return "".join(result)
def _parse_backend_identity(raw: Any) -> BackendIdentityConfig:
data = _as_dict(raw)
return BackendIdentityConfig(

View File

@ -91,6 +91,19 @@ class AuthzConfig:
outlook_mcp_url: str = ""
@dataclass(slots=True)
class ChannelConfig:
"""One configured channel adapter instance."""
enabled: bool = False
kind: str = ""
mode: str = "webhook"
account_id: str = ""
display_name: str = ""
config: dict[str, Any] = field(default_factory=dict)
secrets: dict[str, str] = field(default_factory=dict)
@dataclass(slots=True)
class BackendIdentityConfig:
"""This backend's AuthZ client identity."""
@ -111,6 +124,7 @@ class BeaverConfig:
embedding: EmbeddingConfig = field(default_factory=EmbeddingConfig)
tools: ToolsConfig = field(default_factory=ToolsConfig)
authz: AuthzConfig = field(default_factory=AuthzConfig)
channels: dict[str, ChannelConfig] = field(default_factory=dict)
backend_identity: BackendIdentityConfig = field(default_factory=BackendIdentityConfig)
config_path: Path | None = None