ForcePilot/backend/package/yuxi/channel/extensions/tlon/doctor.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

61 lines
2.0 KiB
Python

class TlonDoctor:
legacy_config_rules = [
{
"old_path": "channels.tlon.allowPrivateNetwork",
"new_path": "channels.tlon.network.dangerouslyAllowPrivateNetwork",
}
]
def normalize_compatibility_config(self, config: dict) -> dict:
result = dict(config)
for rule in self.legacy_config_rules:
old_path = rule["old_path"]
new_path = rule["new_path"]
old_val = self._get_nested(result, old_path)
if old_val is not None:
self._set_nested(result, new_path, old_val)
self._delete_nested(result, old_path)
return result
def check_migration_needed(self, config: dict) -> list[dict]:
migrations = []
for rule in self.legacy_config_rules:
old_val = self._get_nested(config, rule["old_path"])
if old_val is not None:
migrations.append({
"rule": rule,
"current_value": old_val,
})
return migrations
def _get_nested(self, d: dict, path: str):
parts = path.split(".")
current = d
for part in parts:
if not isinstance(current, dict):
return None
current = current.get(part)
return current
def _set_nested(self, d: dict, path: str, value) -> None:
parts = path.split(".")
current = d
for part in parts[:-1]:
if part not in current:
current[part] = {}
current = current[part]
current[parts[-1]] = value
def _delete_nested(self, d: dict, path: str) -> None:
parts = path.split(".")
current = d
for part in parts[:-1]:
if not isinstance(current, dict):
return
current = current.get(part)
if current is None:
return
if isinstance(current, dict):
current.pop(parts[-1], None)