ErisPulse 2.2.1.dev0__py3-none-any.whl → 2.3.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. ErisPulse/Core/Bases/__init__.py +14 -0
  2. ErisPulse/Core/Bases/adapter.py +196 -0
  3. ErisPulse/Core/Bases/module.py +54 -0
  4. ErisPulse/Core/Event/__init__.py +14 -0
  5. ErisPulse/Core/Event/base.py +15 -2
  6. ErisPulse/Core/Event/command.py +21 -2
  7. ErisPulse/Core/Event/message.py +15 -0
  8. ErisPulse/Core/Event/meta.py +15 -0
  9. ErisPulse/Core/Event/notice.py +15 -0
  10. ErisPulse/Core/Event/request.py +16 -1
  11. ErisPulse/Core/__init__.py +38 -19
  12. ErisPulse/Core/{erispulse_config.py → _self_config.py} +27 -2
  13. ErisPulse/Core/adapter.py +374 -377
  14. ErisPulse/Core/config.py +137 -38
  15. ErisPulse/Core/exceptions.py +6 -1
  16. ErisPulse/Core/lifecycle.py +167 -0
  17. ErisPulse/Core/logger.py +97 -49
  18. ErisPulse/Core/module.py +279 -56
  19. ErisPulse/Core/router.py +112 -23
  20. ErisPulse/Core/storage.py +258 -77
  21. ErisPulse/Core/ux.py +635 -0
  22. ErisPulse/__init__.py +722 -244
  23. ErisPulse/__main__.py +1 -1999
  24. ErisPulse/utils/__init__.py +17 -0
  25. ErisPulse/utils/cli.py +1092 -0
  26. ErisPulse/utils/console.py +53 -0
  27. ErisPulse/utils/package_manager.py +845 -0
  28. ErisPulse/utils/reload_handler.py +111 -0
  29. {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/METADATA +24 -6
  30. erispulse-2.3.0.dist-info/RECORD +34 -0
  31. {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/WHEEL +1 -1
  32. {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/licenses/LICENSE +1 -1
  33. ErisPulse/Core/env.py +0 -15
  34. ErisPulse/Core/module_registry.py +0 -227
  35. erispulse-2.2.1.dev0.dist-info/RECORD +0 -26
  36. {erispulse-2.2.1.dev0.dist-info → erispulse-2.3.0.dist-info}/entry_points.txt +0 -0
ErisPulse/Core/module.py CHANGED
@@ -1,66 +1,295 @@
1
1
  """
2
- ErisPulse 模块管理模块
2
+ ErisPulse 模块系统
3
3
 
4
- 提供便捷的模块访问接口
4
+ 提供标准化的模块注册、加载和管理功能,与适配器系统保持一致的设计模式
5
5
  """
6
6
 
7
- from typing import Any, Optional, Dict
8
- from .module_registry import module_registry
7
+ import asyncio
8
+ from typing import Any, Dict, List, Type, Optional
9
9
  from .logger import logger
10
+ from .config import config
11
+ from .Bases import BaseModule
12
+ from .lifecycle import lifecycle
10
13
 
11
14
  class ModuleManager:
12
15
  """
13
16
  模块管理器
14
17
 
15
- 提供便捷的模块访问接口,支持获取模块实例、检查模块状态等操作
18
+ 提供标准化的模块注册、加载和管理功能,模仿适配器管理器的模式
19
+
20
+ {!--< tips >!--}
21
+ 1. 使用register方法注册模块类
22
+ 2. 使用load/unload方法加载/卸载模块
23
+ 3. 通过get方法获取模块实例
24
+ {!--< /tips >!--}
16
25
  """
17
26
 
18
27
  def __init__(self):
19
- self._modules = {}
28
+ # 模块存储
29
+ self._modules: Dict[str, Any] = {} # 已加载的模块实例
30
+ self._module_classes: Dict[str, Type] = {} # 模块类映射
31
+ self._loaded_modules: set = set() # 已加载的模块名称
32
+ self._module_info: Dict[str, Dict] = {} # 模块信息
33
+
34
+ # ==================== 模块注册与管理 ====================
20
35
 
21
- def get(self, module_name: str) -> Any:
36
+ def register(self, module_name: str, module_class: Type, module_info: Optional[Dict] = None) -> bool:
22
37
  """
23
- 获取指定模块的实例
38
+ 注册模块类
24
39
 
25
- :param module_name: [str] 模块名称
26
- :return: [Any] 模块实例或None
40
+ :param module_name: 模块名称
41
+ :param module_class: 模块类
42
+ :param module_info: 模块信息
43
+ :return: 是否注册成功
44
+
45
+ :raises TypeError: 当模块类无效时抛出
46
+
47
+ :example:
48
+ >>> module.register("MyModule", MyModuleClass)
27
49
  """
28
- # 是否已缓存
29
- if module_name in self._modules:
30
- return self._modules[module_name]
50
+ # 严格验证模块类,确保继承自BaseModule
51
+ if not issubclass(module_class, BaseModule):
52
+ warn_msg = f"模块 {module_name} 的类 {module_class.__name__} 没有继承自BaseModule,但我们仍会继续尝试加载这个模块,但请注意这可能引发其他问题"
53
+ logger.warning(warn_msg)
54
+ # error_msg = f"模块 {module_name} 的类 {module_class.__name__} 必须继承自BaseModule"
55
+ # logger.error(error_msg)
56
+ # raise TypeError(error_msg)
57
+
58
+ # 验证模块名是否合法
59
+ if not module_name or not isinstance(module_name, str):
60
+ error_msg = "模块名称必须是非空字符串"
61
+ logger.error(error_msg)
62
+ raise TypeError(error_msg)
31
63
 
32
- # 从模块注册表获取模块信息
33
- module_info = module_registry.get_module(module_name)
34
- if not module_info:
35
- logger.warning(f"模块 {module_name} 未注册")
36
- return None
64
+ # 检查模块名是否已存在
65
+ if module_name in self._module_classes:
66
+ logger.warning(f"模块 {module_name} 已存在,将覆盖原模块类")
37
67
 
38
- # 模块是否启用
39
- if not module_registry.get_module_status(module_name):
40
- logger.warning(f"模块 {module_name} 已禁用")
41
- return None
68
+ self._module_classes[module_name] = module_class
69
+ if module_info:
70
+ self._module_info[module_name] = module_info
71
+
72
+ logger.info(f"模块 {module_name} 已注册")
73
+ return True
74
+
75
+ async def load(self, module_name: str) -> bool:
76
+ """
77
+ 加载指定模块(标准化加载逻辑)
78
+
79
+ :param module_name: 模块名称
80
+ :return: 是否加载成功
81
+
82
+ :example:
83
+ >>> await module.load("MyModule")
84
+ """
85
+ # 检查模块是否已注册
86
+ if module_name not in self._module_classes:
87
+ logger.error(f"模块 {module_name} 未注册")
88
+ return False
89
+
90
+ # 检查模块是否已加载
91
+ if module_name in self._loaded_modules:
92
+ logger.info(f"模块 {module_name} 已加载")
93
+ return True
42
94
 
43
95
  try:
44
96
  from .. import sdk
45
- if hasattr(sdk, module_name):
46
- module_instance = getattr(sdk, module_name)
47
- self._modules[module_name] = module_instance
48
- return module_instance
97
+ import inspect
98
+
99
+ # 创建模块实例
100
+ module_class = self._module_classes[module_name]
101
+
102
+ # 检查是否需要传入sdk参数
103
+ init_signature = inspect.signature(module_class.__init__)
104
+ params = init_signature.parameters
105
+
106
+ if 'sdk' in params:
107
+ instance = module_class(sdk)
49
108
  else:
50
- logger.warning(f"模块 {module_name} 实例未找到")
51
- return None
109
+ instance = module_class()
110
+
111
+ # 设置模块信息
112
+ if module_name in self._module_info:
113
+ setattr(instance, "moduleInfo", self._module_info[module_name])
114
+
115
+ # 调用模块的on_load卸载方法
116
+ if hasattr(instance, 'on_load'):
117
+ try:
118
+ if asyncio.iscoroutinefunction(instance.on_load):
119
+ await instance.on_load({"module_name": module_name})
120
+ else:
121
+ instance.on_load({"module_name": module_name})
122
+ except Exception as e:
123
+ logger.error(f"模块 {module_name} on_load 方法执行失败: {e}")
124
+ return False
125
+
126
+ # 缓存模块实例
127
+ self._modules[module_name] = instance
128
+ self._loaded_modules.add(module_name)
129
+
130
+ await lifecycle.submit_event(
131
+ "module_load",
132
+ data={
133
+ "module_name": module_name,
134
+ "success": True,
135
+ },
136
+ msg=f"模块 {module_name if module_name else 'All'} 加载成功",
137
+ )
138
+ logger.info(f"模块 {module_name} 加载成功")
139
+ return True
140
+
52
141
  except Exception as e:
53
- logger.error(f"获取模块 {module_name} 实例时出错: {e}")
54
- return None
142
+ await lifecycle.submit_event(
143
+ "module_load",
144
+ data={
145
+ "module_name": module_name,
146
+ "success": False,
147
+ },
148
+ msg=f"模块 {module_name if module_name else 'All'} 加载失败: {e}",
149
+ )
150
+ logger.error(f"加载模块 {module_name} 失败: {e}")
151
+ return False
152
+
153
+ async def unload(self, module_name: str = "Unknown") -> bool:
154
+ """
155
+ 卸载指定模块或所有模块
156
+
157
+ :param module_name: 模块名称,如果为None则卸载所有模块
158
+ :return: 是否卸载成功
159
+
160
+ :example:
161
+ >>> await module.unload("MyModule")
162
+ >>> await module.unload() # 卸载所有模块
163
+ """
164
+ if module_name == "Unknown":
165
+ # 卸载所有模块
166
+ success = True
167
+ for name in list(self._loaded_modules):
168
+ if not await self._unload_single_module(name):
169
+ success = False
170
+ return success
171
+ else:
172
+ success = await self._unload_single_module(module_name)
173
+
174
+ await lifecycle.submit_event(
175
+ "module.unload",
176
+ msg=f"模块 {module_name if module_name else 'All'} 卸载完成" if success else f"模块 {module_name if module_name else 'All'} 卸载失败",
177
+ data={
178
+ "module_name": module_name if module_name else 'All',
179
+ "success": success
180
+ }
181
+ )
182
+ return success
55
183
 
184
+ async def _unload_single_module(self, module_name: str) -> bool:
185
+ """
186
+ {!--< internal-use >!--}
187
+ 卸载单个模块
188
+
189
+ :param module_name: 模块名称
190
+ :return: 是否卸载成功
191
+ """
192
+ if module_name not in self._loaded_modules:
193
+ logger.warning(f"模块 {module_name} 未加载")
194
+ return False
195
+
196
+ try:
197
+ # 调用模块的on_unload卸载方法
198
+ instance = self._modules[module_name]
199
+ if hasattr(instance, 'on_unload'):
200
+ try:
201
+ if asyncio.iscoroutinefunction(instance.on_unload):
202
+ await instance.on_unload({"module_name": module_name})
203
+ else:
204
+ instance.on_unload({"module_name": module_name})
205
+ except Exception as e:
206
+ logger.error(f"模块 {module_name} on_unload 方法执行失败: {e}")
207
+
208
+ # 清理缓存
209
+ del self._modules[module_name]
210
+ self._loaded_modules.discard(module_name)
211
+
212
+ logger.info(f"模块 {module_name} 卸载成功")
213
+ return True
214
+
215
+ except Exception as e:
216
+ logger.error(f"卸载模块 {module_name} 失败: {e}")
217
+ return False
218
+
219
+ def get(self, module_name: str) -> Any:
220
+ """
221
+ 获取模块实例
222
+
223
+ :param module_name: 模块名称
224
+ :return: 模块实例或None
225
+
226
+ :example:
227
+ >>> my_module = module.get("MyModule")
228
+ """
229
+ return self._modules.get(module_name)
230
+
56
231
  def exists(self, module_name: str) -> bool:
57
232
  """
58
- 检查模块是否存在
233
+ 检查模块是否存在(在配置中注册)
59
234
 
60
235
  :param module_name: [str] 模块名称
61
236
  :return: [bool] 模块是否存在
62
237
  """
63
- return module_registry.get_module(module_name) is not None
238
+ module_statuses = config.getConfig("ErisPulse.modules.status", {})
239
+ return module_name in module_statuses
240
+
241
+ def is_loaded(self, module_name: str) -> bool:
242
+ """
243
+ 检查模块是否已加载
244
+
245
+ :param module_name: 模块名称
246
+ :return: 模块是否已加载
247
+
248
+ :example:
249
+ >>> if module.is_loaded("MyModule"): ...
250
+ """
251
+ return module_name in self._loaded_modules
252
+
253
+ def list_registered(self) -> List[str]:
254
+ """
255
+ 列出所有已注册的模块
256
+
257
+ :return: 模块名称列表
258
+
259
+ :example:
260
+ >>> registered = module.list_registered()
261
+ """
262
+ return list(self._module_classes.keys())
263
+
264
+ def list_loaded(self) -> List[str]:
265
+ """
266
+ 列出所有已加载的模块
267
+
268
+ :return: 模块名称列表
269
+
270
+ :example:
271
+ >>> loaded = module.list_loaded()
272
+ """
273
+ return list(self._loaded_modules)
274
+
275
+ # ==================== 模块配置管理 ====================
276
+
277
+ def _config_register(self, module_name: str, enabled: bool = False) -> bool:
278
+ """
279
+ 注册新模块信息
280
+
281
+ :param module_name: [str] 模块名称
282
+ :param enabled: [bool] 是否启用模块
283
+ :return: [bool] 操作是否成功
284
+ """
285
+ if self.exists(module_name):
286
+ return True
287
+
288
+ # 模块不存在,进行注册
289
+ config.setConfig(f"ErisPulse.modules.status.{module_name}", enabled)
290
+ status = "启用" if enabled else "禁用"
291
+ logger.info(f"模块 {module_name} 已注册并{status}")
292
+ return True
64
293
 
65
294
  def is_enabled(self, module_name: str) -> bool:
66
295
  """
@@ -69,7 +298,15 @@ class ModuleManager:
69
298
  :param module_name: [str] 模块名称
70
299
  :return: [bool] 模块是否启用
71
300
  """
72
- return module_registry.get_module_status(module_name)
301
+ status = config.getConfig(f"ErisPulse.modules.status.{module_name}")
302
+
303
+ if status is None:
304
+ return False
305
+
306
+ if isinstance(status, str):
307
+ return status.lower() not in ('false', '0', 'no', 'off')
308
+
309
+ return bool(status)
73
310
 
74
311
  def enable(self, module_name: str) -> bool:
75
312
  """
@@ -78,11 +315,7 @@ class ModuleManager:
78
315
  :param module_name: [str] 模块名称
79
316
  :return: [bool] 操作是否成功
80
317
  """
81
- if not self.exists(module_name):
82
- logger.error(f"模块 {module_name} 不存在")
83
- return False
84
-
85
- module_registry.set_module_status(module_name, True)
318
+ config.setConfig(f"ErisPulse.modules.status.{module_name}", True)
86
319
  logger.info(f"模块 {module_name} 已启用")
87
320
  return True
88
321
 
@@ -93,33 +326,23 @@ class ModuleManager:
93
326
  :param module_name: [str] 模块名称
94
327
  :return: [bool] 操作是否成功
95
328
  """
96
- if not self.exists(module_name):
97
- logger.error(f"模块 {module_name} 不存在")
98
- return False
99
-
100
- module_registry.set_module_status(module_name, False)
329
+ config.setConfig(f"ErisPulse.modules.status.{module_name}", False)
101
330
  logger.info(f"模块 {module_name} 已禁用")
102
- # 如果模块在缓存中,移除它
331
+
103
332
  if module_name in self._modules:
104
333
  del self._modules[module_name]
334
+ self._loaded_modules.discard(module_name)
105
335
  return True
106
336
 
107
- def list_modules(self) -> Dict[str, Dict[str, Any]]:
337
+ def list_modules(self) -> Dict[str, bool]:
108
338
  """
109
- 列出所有模块信息
339
+ 列出所有模块状态
110
340
 
111
- :return: [Dict[str, Dict[str, Any]]] 模块信息字典
341
+ :return: [Dict[str, bool]] 模块状态字典
112
342
  """
113
- return module_registry.get_all_modules()
343
+ return config.getConfig("ErisPulse.modules.status", {})
114
344
 
115
- def get_info(self, module_name: str) -> Optional[Dict[str, Any]]:
116
- """
117
- 获取模块详细信息
118
-
119
- :param module_name: [str] 模块名称
120
- :return: [Optional[Dict[str, Any]]] 模块信息字典
121
- """
122
- return module_registry.get_module(module_name)
345
+ # ==================== 工具方法 ====================
123
346
 
124
347
  def __getattr__(self, module_name: str) -> Any:
125
348
  """
ErisPulse/Core/router.py CHANGED
@@ -1,4 +1,3 @@
1
- # router.py (新文件名)
2
1
  """
3
2
  ErisPulse 路由系统
4
3
 
@@ -7,7 +6,6 @@ ErisPulse 路由系统
7
6
  {!--< tips >!--}
8
7
  1. 适配器只需注册路由,无需自行管理服务器
9
8
  2. WebSocket支持自定义认证逻辑
10
- 3. 兼容FastAPI 0.68+ 版本
11
9
  {!--< /tips >!--}
12
10
  """
13
11
 
@@ -16,6 +14,7 @@ from fastapi.routing import APIRoute
16
14
  from typing import Dict, List, Optional, Callable, Any, Awaitable, Tuple
17
15
  from collections import defaultdict
18
16
  from .logger import logger
17
+ from .lifecycle import lifecycle
19
18
  import asyncio
20
19
  from hypercorn.config import Config
21
20
  from hypercorn.asyncio import serve
@@ -140,7 +139,8 @@ class RouterManager:
140
139
  )
141
140
  self.app.router.routes.append(route)
142
141
  self._http_routes[module_name][full_path] = handler
143
- logger.info(f"注册HTTP路由: {self.base_url}{full_path} 方法: {methods}")
142
+ display_url = self._format_display_url(f"{self.base_url}{full_path}")
143
+ logger.info(f"注册HTTP路由: {display_url} 方法: {methods}")
144
144
 
145
145
  def register_webhook(self, *args, **kwargs) -> None:
146
146
  """
@@ -148,6 +148,38 @@ class RouterManager:
148
148
  """
149
149
  return self.register_http_route(*args, **kwargs)
150
150
 
151
+ def unregister_http_route(self, module_name: str, path: str) -> bool:
152
+ """
153
+ 取消注册HTTP路由
154
+
155
+ :param module_name: 模块名称
156
+ :param path: 路由路径
157
+
158
+ :return: Bool
159
+ """
160
+ try:
161
+ full_path = f"/{module_name}{path}"
162
+ if full_path not in self._http_routes[module_name]:
163
+ display_url = self._format_display_url(f"{self.base_url}{full_path}")
164
+ logger.warning(f"取消注册HTTP路由失败: 路由不存在: {display_url}")
165
+ return False
166
+
167
+ display_url = self._format_display_url(f"{self.base_url}{full_path}")
168
+ logger.info(f"取消注册HTTP路由: {display_url}")
169
+ del self._http_routes[module_name][full_path]
170
+
171
+ # 从路由列表中移除匹配的路由
172
+ routes = self.app.router.routes
173
+ self.app.router.routes = [
174
+ route for route in routes
175
+ if not (isinstance(route, APIRoute) and route.path == full_path)
176
+ ]
177
+
178
+ return True
179
+ except Exception as e:
180
+ logger.error(f"取消注册HTTP路由失败: {e}")
181
+ return False
182
+
151
183
  def register_websocket(
152
184
  self,
153
185
  module_name: str,
@@ -195,8 +227,28 @@ class RouterManager:
195
227
  name=f"{module_name}_{path.replace('/', '_')}"
196
228
  )
197
229
  self._websocket_routes[module_name][full_path] = (handler, auth_handler)
198
- logger.info(f"注册WebSocket: {self.base_url}{full_path} {'(需认证)' if auth_handler else ''}")
199
230
 
231
+ display_url = self._format_display_url(f"{self.base_url}{full_path}")
232
+ logger.info(f"注册WebSocket: {display_url} {'(需认证)' if auth_handler else ''}")
233
+
234
+ def unregister_websocket(self, module_name: str, path: str) -> bool:
235
+ try:
236
+ full_path = f"/{module_name}{path}"
237
+
238
+ # 使用类型忽略注释
239
+ if full_path in self.app.websocket_routes: # type: ignore || 原因:实际上,FastAPI的API提供了websocket_routes属性
240
+ self.app.remove_api_websocket_route(full_path) # type: ignore || 原因:实际上,FastAPI的API提供了remove_api_websocket_route方法
241
+ display_url = self._format_display_url(f"{self.base_url}{full_path}")
242
+ logger.info(f"注销WebSocket: {display_url}")
243
+ del self._websocket_routes[module_name][full_path]
244
+ return True
245
+ display_url = self._format_display_url(f"{self.base_url}{full_path}")
246
+ logger.error(f"注销WebSocket失败: 路径 {display_url} 不存在")
247
+ return False
248
+ except Exception as e:
249
+ logger.error(f"注销WebSocket失败: {e}")
250
+ return False
251
+
200
252
  def get_app(self) -> FastAPI:
201
253
  """
202
254
  获取FastAPI应用实例
@@ -222,21 +274,46 @@ class RouterManager:
222
274
 
223
275
  :raises RuntimeError: 当服务器已在运行时抛出
224
276
  """
225
- if self._server_task and not self._server_task.done():
226
- raise RuntimeError("服务器已在运行中")
277
+ try:
278
+ if self._server_task and not self._server_task.done():
279
+ raise RuntimeError("服务器已在运行中")
227
280
 
228
- config = Config()
229
- config.bind = [f"{host}:{port}"]
230
- config.loglevel = "warning"
231
-
232
- if ssl_certfile and ssl_keyfile:
233
- config.certfile = ssl_certfile
234
- config.keyfile = ssl_keyfile
235
-
236
- self.base_url = f"http{'s' if ssl_certfile else ''}://{host}:{port}"
237
- logger.info(f"启动路由服务器 {self.base_url}")
238
-
239
- self._server_task = asyncio.create_task(serve(self.app, config))
281
+ config = Config()
282
+ config.bind = [f"{host}:{port}"]
283
+ config.loglevel = "warning"
284
+
285
+ if ssl_certfile and ssl_keyfile:
286
+ config.certfile = ssl_certfile
287
+ config.keyfile = ssl_keyfile
288
+
289
+ self.base_url = f"http{'s' if ssl_certfile else ''}://{host}:{port}"
290
+ display_url = self._format_display_url(self.base_url)
291
+ logger.info(f"启动路由服务器 {display_url}")
292
+
293
+ self._server_task = asyncio.create_task(serve(self.app, config)) # type: ignore || 原因: Hypercorn与FastAPIl类型不兼容
294
+
295
+ await lifecycle.submit_event(
296
+ "server.start",
297
+ msg="路由服务器已启动",
298
+ data={
299
+ "base_url": self.base_url,
300
+ "host": host,
301
+ "port": port,
302
+ },
303
+ )
304
+ except Exception as e:
305
+ display_url = self._format_display_url(self.base_url)
306
+ await lifecycle.submit_event(
307
+ "server.start",
308
+ msg="路由服务器启动失败",
309
+ data={
310
+ "base_url": self.base_url,
311
+ "host": host,
312
+ "port": port,
313
+ }
314
+ )
315
+ logger.error(f"启动服务器失败: {e}")
316
+ raise e
240
317
 
241
318
  async def stop(self) -> None:
242
319
  """
@@ -249,14 +326,26 @@ class RouterManager:
249
326
  except asyncio.CancelledError:
250
327
  logger.info("路由服务器已停止")
251
328
  self._server_task = None
329
+
330
+ await lifecycle.submit_event("server.stop", msg="服务器已停止")
252
331
 
253
- # 主要实例
254
- router = RouterManager()
332
+ def _format_display_url(self, url: str) -> str:
333
+ """
334
+ 格式化URL显示,将回环地址转换为更友好的格式
335
+
336
+ :param url: 原始URL
337
+ :return: 格式化后的URL
338
+ """
339
+ if "0.0.0.0" in url:
340
+ display_url = url.replace("0.0.0.0", "127.0.0.1")
341
+ return f"{url} (可访问: {display_url})"
342
+ elif "::" in url:
343
+ display_url = url.replace("::", "localhost")
344
+ return f"{url} (可访问: {display_url})"
345
+ return url
255
346
 
256
- # 兼容性实例
257
- adapter_server = router
347
+ router = RouterManager()
258
348
 
259
349
  __all__ = [
260
350
  "router",
261
- "adapter_server"
262
351
  ]