ForcePilot/backend/package/yuxi/channel/extensions/tlon/config.py
Kris 0babb1ca8e feat(channel): 添加 Tlon 渠道扩展
新增 Tlon 渠道扩展,支持在 Yuxi 平台中集成 Tlon/Urbit 去中心化通讯平台。

包含以下功能模块:
- tlon_api: Tlon API 客户端封装
- config: 渠道配置管理
- gateway: SSE/WebSocket 网关接入
- sse_client: SSE 客户端
- outbound: 外发消息管理
- send: 消息发送
- security: 安全校验
- auth: 认证管理
- monitor: 渠道状态监控
- status: 会话状态管理
- session: 会话管理
- approval: 审批流程
- channel_mgmt: 频道管理
- channel_ops: 频道操作
- contacts: 联系人管理
- discovery: 服务发现
- doctor: 健康诊断
- expose: 服务暴露
- gallery: 图库管理
- history: 历史记录
- hooks: 钩子管理
- media: 媒体资源处理
- notebook: 笔记本功能
- settings_store: 设置存储
- setup: 初始化设置
- story: 故事功能
- targets: 目标管理
- cite_parser: 引用解析
- utils: 工具函数
- types: 类型定义
2026-05-21 11:55:25 +08:00

123 lines
4.6 KiB
Python

from yuxi.channel.extensions.tlon.utils import normalize_ship
TLON_CONFIG_SCHEMA = {
"type": "object",
"properties": {
"name": {"type": "string"},
"enabled": {"type": "boolean", "default": True},
"ship": {"type": "string", "minLength": 1, "pattern": "^~?[a-z-]+$"},
"url": {"type": "string", "minLength": 1, "format": "uri"},
"code": {"type": "string", "minLength": 1},
"network": {
"type": "object",
"properties": {
"dangerouslyAllowPrivateNetwork": {"type": "boolean"},
},
},
"groupChannels": {
"type": "array",
"items": {"type": "string"},
},
"dmAllowlist": {
"type": "array",
"items": {"type": "string"},
},
"groupInviteAllowlist": {
"type": "array",
"items": {"type": "string"},
},
"autoDiscoverChannels": {"type": "boolean"},
"showModelSignature": {"type": "boolean"},
"autoAcceptDmInvites": {"type": "boolean"},
"autoAcceptGroupInvites": {"type": "boolean"},
"ownerShip": {"type": "string"},
"defaultAuthorizedShips": {
"type": "array",
"items": {"type": "string"},
},
"authorization": {
"type": "object",
"properties": {
"channelRules": {
"type": "object",
"additionalProperties": {
"type": "object",
"properties": {
"mode": {"enum": ["restricted", "open"]},
"allowedShips": {
"type": "array",
"items": {"type": "string"},
},
},
},
},
},
},
"accounts": {
"type": "object",
"additionalProperties": {"$ref": "#"},
},
},
}
class TlonConfigAdapter:
def list_account_ids(self, config: dict) -> list[str]:
accounts = config.get("channels", {}).get("tlon", {}).get("accounts", {})
if accounts:
return list(accounts.keys())
return ["default"]
def resolve_account(self, account_id: str, config: dict | None = None) -> dict:
if config is None:
return {"account_id": account_id}
tlon_config = config.get("channels", {}).get("tlon", {})
account = tlon_config.get("accounts", {}).get(account_id, tlon_config)
return {
"account_id": account_id,
"ship": account.get("ship"),
"url": account.get("url"),
"code": account.get("code"),
"name": account.get("name"),
"network": account.get("network", {}),
"group_channels": account.get("groupChannels", []),
"dm_allowlist": account.get("dmAllowlist", []),
"group_invite_allowlist": account.get("groupInviteAllowlist", []),
"auto_discover_channels": account.get("autoDiscoverChannels", False),
"show_model_signature": account.get("showModelSignature", False),
"auto_accept_dm_invites": account.get("autoAcceptDmInvites", False),
"auto_accept_group_invites": account.get("autoAcceptGroupInvites", False),
"owner_ship": account.get("ownerShip"),
"default_authorized_ships": account.get("defaultAuthorizedShips", []),
"authorization": account.get("authorization", {}),
}
def is_configured(self, account: dict) -> bool:
return bool(account.get("ship") and account.get("url") and account.get("code"))
def is_enabled(self, account: dict) -> bool:
return account.get("enabled", True)
def disabled_reason(self, account: dict) -> str:
if self.is_configured(account):
return ""
missing = []
if not account.get("ship"):
missing.append("ship")
if not account.get("url"):
missing.append("url")
if not account.get("code"):
missing.append("code")
return f"Account not configured (missing {', '.join(missing)})"
def describe_account(self, account: dict) -> dict:
ship = account.get("ship", "")
return {
"account_id": account.get("account_id", "default"),
"label": ship,
"display": f"{ship} ({account.get('url', '')})",
}
def normalize_ships_in_allowlist(self, allowlist: list[str]) -> list[str]:
return [normalize_ship(s) for s in allowlist if s.strip()]