ForcePilot/backend/package/yuxi/channels/adapters/imessage/config_schema.py

117 lines
3.6 KiB
Python
Raw Normal View History

from __future__ import annotations
from enum import StrEnum
from pydantic import BaseModel, Field, field_validator
class DmPolicyEnum(StrEnum):
PAIRING = "pairing"
ALLOWLIST = "allowlist"
OPEN = "open"
DISABLED = "disabled"
class GroupPolicyEnum(StrEnum):
OPEN = "open"
ALLOWLIST = "allowlist"
DISABLED = "disabled"
class IMessageConnectionConfig(BaseModel):
server_url: str = "http://localhost:1234"
password: str = ""
probe_timeout_ms: int = Field(default=10000, ge=1000, le=60000)
max_retries: int = Field(default=3, ge=1, le=10)
http_timeout_s: float = Field(default=30.0, ge=1.0, le=300.0)
class IMessageSecurityConfigSchema(BaseModel):
dm_policy: DmPolicyEnum = DmPolicyEnum.PAIRING
group_policy: GroupPolicyEnum = GroupPolicyEnum.ALLOWLIST
allow_from: list[str] = Field(default_factory=list)
group_allow_from: list[str] = Field(default_factory=list)
require_mention: bool = False
@field_validator("dm_policy", mode="before")
@classmethod
def coerce_dm_policy(cls, v):
if isinstance(v, str):
try:
return DmPolicyEnum(v)
except ValueError:
return DmPolicyEnum.PAIRING
return v
@field_validator("group_policy", mode="before")
@classmethod
def coerce_group_policy(cls, v):
if isinstance(v, str):
try:
return GroupPolicyEnum(v)
except ValueError:
return GroupPolicyEnum.ALLOWLIST
return v
class GroupOverrideConfig(BaseModel):
enabled: bool | None = None
require_mention: bool | None = None
tools: list[str] | None = None
class IMessageAccountConfig(BaseModel):
account_id: str = "default"
name: str = ""
connection: IMessageConnectionConfig = Field(default_factory=IMessageConnectionConfig)
security: IMessageSecurityConfigSchema = Field(default_factory=IMessageSecurityConfigSchema)
enabled: bool = True
default_to: str = ""
class IMessageFullConfig(BaseModel):
name: str = "iMessage"
connection: IMessageConnectionConfig = Field(default_factory=IMessageConnectionConfig)
security: IMessageSecurityConfigSchema = Field(default_factory=IMessageSecurityConfigSchema)
config_writes: bool = True
block_streaming: bool = False
text_chunk_limit: int = Field(default=4096, ge=100, le=16000)
media_max_mb: int = Field(default=100, ge=1, le=1000)
history_limit: int = Field(default=20, ge=1, le=200)
default_account: str = ""
default_to: str = ""
accounts: dict[str, IMessageAccountConfig] = Field(default_factory=dict)
include_attachments: bool = False
attachment_roots: list[str] = Field(default_factory=list)
remote_attachment_roots: list[str] = Field(default_factory=list)
groups: dict[str, GroupOverrideConfig] = Field(default_factory=dict)
ws_reconnect_initial_delay: float = Field(default=5.0, ge=0.5, le=120.0)
ws_reconnect_max_delay: float = Field(default=60.0, ge=1.0, le=600.0)
loop_rate_limit: int = Field(default=5, ge=0, le=50)
loop_rate_window_s: float = Field(default=60.0, ge=1.0, le=600.0)
loop_cooldown_s: float = Field(default=120.0, ge=1.0, le=3600.0)
@field_validator("accounts", mode="before")
@classmethod
def coerce_accounts(cls, v):
if v is None:
return {}
if isinstance(v, list):
return {a.account_id: a for a in v}
return v
def validate_config(config: dict) -> IMessageFullConfig:
"""校验并标准化 iMessage 配置。
Raises:
ValidationError: 配置不符合 Schema 时抛出
"""
return IMessageFullConfig(**config)