新增 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: 类型定义
123 lines
4.6 KiB
Python
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()] |