完成阶段2

This commit is contained in:
Falck
2026-04-25 20:29:05 +08:00
committed by GitHub
20 changed files with 186 additions and 66 deletions

66
.gitignore vendored
View File

@@ -1,10 +1,47 @@
```gitignore
```
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
*.pyc
*.pyo
*.pyd
.Python
env/
venv/
.venv/
pip-log.txt
pip-delete-this-directory.txt
.tox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.log
*.pot
*.mo
MoeMyanmar-*
!MoeMyanmar-*/**/*.py
!MoeMyanmar-*/**/*.txt
!MoeMyanmar-*/**/*.md
!MoeMyanmar-*/**/*.json
!MoeMyanmar-*/**/*.yml
!MoeMyanmar-*/**/*.yaml
julia-*/
zig*/
# Dependencies
node_modules/
target/
.gradle/
.mypy_cache/
.pytest_cache/
.hypothesis/
# Distribution / packaging
.Python
_build/
buck-out/
build/
develop-eggs/
dist/
@@ -21,19 +58,28 @@ wheels/
.installed.cfg
*.egg
# IDE
# IDEs
.vscode/
.idea/
*.swp
*.swo
# Environment
# System
.DS_Store
Thumbs.db
.env
.env.local
.env.*
*.env.*
# Logs
*.log
# OS
.DS_Store
Thumbs.db
# Coverage
coverage/
htmlcov/
.coverage
# Temporary files
*.tmp
*.temp
```

View File

@@ -64,7 +64,7 @@ class Config:
if key in self.DEFAULTS:
self._config[key] = value
except Exception as e:
print(f"[Config] 加载配置文件失败:{e}")
print(f"[Config] 加载配置文件失败:{type(e).__name__}: {e}")
def _load_from_env(self):
"""从环境变量加载"""

View File

@@ -86,7 +86,8 @@ class SystemDependencyChecker:
timeout=30
)
return result.returncode == 0
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
pass
return False
@@ -144,7 +145,8 @@ class SystemDependencyChecker:
timeout=300
)
return result.returncode == 0
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
pass
return False
@@ -249,7 +251,8 @@ class AutoDependencyPlugin(Plugin):
"manifest": manifest,
"system_dependencies": system_deps
})
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
continue
return results

View File

@@ -89,7 +89,8 @@ class DashboardPlugin(Plugin):
sent_rate = (net.bytes_sent - self._last_net[2]) / elapsed
self._last_net = (now, net.bytes_recv, net.bytes_sent)
return {'recv_rate': round(recv_rate, 1), 'sent_rate': round(sent_rate, 1), 'total_recv': net.bytes_recv, 'total_sent': net.bytes_sent}
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
return {'recv_rate': 0, 'sent_rate': 0, 'total_recv': 0, 'total_sent': 0}
def _get_disk_io_stats(self):
@@ -107,7 +108,8 @@ class DashboardPlugin(Plugin):
write_rate = (disk_io.write_bytes - self._last_disk[2]) / elapsed
self._last_disk = (now, disk_io.read_bytes, disk_io.write_bytes)
return {'read_rate': round(read_rate, 1), 'write_rate': round(write_rate, 1)}
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
return {'read_rate': 0, 'write_rate': 0}
def _get_network_latency(self) -> float:
@@ -120,7 +122,8 @@ class DashboardPlugin(Plugin):
elapsed = (time.time() - start) * 1000 # 毫秒
s.close()
return round(elapsed, 1)
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
return 0.0
def _get_network_interfaces(self):
@@ -142,7 +145,8 @@ class DashboardPlugin(Plugin):
info['speed'] = stats[name].speed
interfaces.append(info)
return interfaces
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
return []
def _get_load_info(self):

View File

@@ -139,7 +139,7 @@ class HotReloadPlugin(Plugin):
elif change_type == "deleted":
self.unload_plugin(plugin_name)
except Exception as e:
Log.error("hot-reload", f"处理变化失败: {e}")
Log.error("hot-reload", f"处理变化失败: {type(e).__name__}: {e}")
def load_plugin(self, plugin_dir: Path) -> bool:
"""运行时加载插件"""

View File

@@ -39,7 +39,8 @@ class HttpEventBus:
for handler in handlers:
try:
handler(event)
except Exception:
except Exception as e:
import traceback; print(f"[events.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
pass
def clear(self):

View File

@@ -133,9 +133,18 @@ class TcpHttpServer:
buffer = b""
except ConnectionResetError:
# 客户端断开连接,正常情况
pass
except BrokenPipeError:
# 管道破裂,正常情况
pass
except OSError as e:
if self.event_bus:
self.event_bus.emit(TcpEvent(type=EVENT_ERROR, client=client, context={"error": f"OSError: {e}"}))
except Exception as e:
if self.event_bus:
self.event_bus.emit(TcpEvent(type=EVENT_ERROR, client=client, context={"error": str(e)}))
self.event_bus.emit(TcpEvent(type=EVENT_ERROR, client=client, context={"error": f"{type(e).__name__}: {e}"}))
finally:
del self._clients[client.id]
client.close()
@@ -179,7 +188,13 @@ class TcpHttpServer:
"headers": headers,
"body": body,
}
except Exception:
except UnicodeDecodeError:
return None
except ValueError:
return None
except Exception as e:
# 其他解析错误
import traceback; print(f"[http-tcp] HTTP 解析失败:{type(e).__name__}: {e}"); traceback.print_exc()
return None
def _format_response(self, response: dict) -> bytes:

View File

@@ -151,7 +151,8 @@ class LogTerminalPlugin(Plugin):
try:
if 'process' in session:
session['process'].terminate()
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
pass
self._ssh_sessions.clear()
@@ -192,13 +193,14 @@ class LogTerminalPlugin(Plugin):
if line:
self.add_log_entry("info", "system", line)
except Exception as e:
pass
import traceback
traceback.print_exc()
# 等待下一次同步
time.sleep(2)
except Exception as e:
Log.error("log-terminal", f"日志同步线程异常: {e}")
Log.error("log-terminal", f"日志同步线程异常: {type(e).__name__}: {e}")
def add_log_entry(self, level: str, tag: str, message: str):
"""向日志缓冲区添加日志条目"""
@@ -226,7 +228,8 @@ class LogTerminalPlugin(Plugin):
try:
result = subprocess.run(['which', 'sshd'], capture_output=True, text=True, timeout=5)
return result.returncode == 0
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
return False
def _install_ssh(self):
@@ -264,7 +267,7 @@ class LogTerminalPlugin(Plugin):
Log.error("log-terminal", "未找到支持的包管理器")
return False
except Exception as e:
Log.error("log-terminal", f"安装 SSH 服务时出错: {e}")
Log.error("log-terminal", f"安装 SSH 服务时出错: {type(e).__name__}: {e}")
return False
def _start_ssh_server(self, port=8022):
@@ -290,7 +293,7 @@ class LogTerminalPlugin(Plugin):
Log.error("log-terminal", "SSH 服务器启动失败")
return False
except Exception as e:
Log.error("log-terminal", f"启动 SSH 服务器时出错: {e}")
Log.error("log-terminal", f"启动 SSH 服务器时出错: {type(e).__name__}: {e}")
return False
def _handle_connect_ssh(self, request):
@@ -357,7 +360,7 @@ class LogTerminalPlugin(Plugin):
})
)
except Exception as e:
Log.error("log-terminal", f"创建终端会话失败: {e}")
Log.error("log-terminal", f"创建终端会话失败: {type(e).__name__}: {e}")
return Response(
status=500,
headers={"Content-Type": "application/json"},
@@ -365,7 +368,7 @@ class LogTerminalPlugin(Plugin):
)
except Exception as e:
Log.error("log-terminal", f"SSH 连接请求异常: {e}")
Log.error("log-terminal", f"SSH 连接请求异常: {type(e).__name__}: {e}")
return Response(
status=500,
headers={"Content-Type": "application/json"},
@@ -402,7 +405,8 @@ class LogTerminalPlugin(Plugin):
if not line:
break
output += line
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
pass
return Response(
@@ -414,7 +418,7 @@ class LogTerminalPlugin(Plugin):
})
)
except Exception as e:
Log.error("log-terminal", f"发送命令时出错: {e}")
Log.error("log-terminal", f"发送命令时出错: {type(e).__name__}: {e}")
return Response(
status=500,
headers={"Content-Type": "application/json"},
@@ -431,7 +435,8 @@ class LogTerminalPlugin(Plugin):
session = self._ssh_sessions[session_id]
try:
session['process'].terminate()
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
pass
del self._ssh_sessions[session_id]
Log.info("log-terminal", f"SSH 终端会话 #{session_id} 已断开")
@@ -447,7 +452,7 @@ class LogTerminalPlugin(Plugin):
body=json.dumps({'success': False, 'error': '会话不存在'})
)
except Exception as e:
Log.error("log-terminal", f"断开连接时出错: {e}")
Log.error("log-terminal", f"断开连接时出错: {type(e).__name__}: {e}")
return Response(
status=500,
headers={"Content-Type": "application/json"},
@@ -545,7 +550,8 @@ class LogTerminalPlugin(Plugin):
'tag': 'system',
'message': line
})
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
pass
return logs[-limit:]

View File

@@ -393,7 +393,8 @@ class PkgManagerPlugin(Plugin):
with _gitee_request(author_url, timeout=15) as resp:
plugin_dirs = json.loads(resp.read().decode("utf-8"))
break
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
if attempt < 2:
time.sleep(1 + attempt)
continue
@@ -413,7 +414,8 @@ class PkgManagerPlugin(Plugin):
with _gitee_request(manifest_url, timeout=15) as resp:
manifest = json.loads(resp.read().decode("utf-8"))
break
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
if attempt < 2:
time.sleep(1 + attempt)
continue
@@ -433,7 +435,7 @@ class PkgManagerPlugin(Plugin):
self._remote_cache = plugins
self._cache_time = now
except Exception as e:
Log.error("pkg-manager", f"获取远程插件列表失败: {e}")
Log.error("pkg-manager", f"获取远程插件列表失败: {type(e).__name__}: {e}")
return plugins
@@ -472,7 +474,7 @@ class PkgManagerPlugin(Plugin):
Log.info("pkg-manager", f"已安装: {author}/{plugin_name}")
return True
except Exception as e:
Log.error("pkg-manager", f"安装失败 {plugin_name}: {e}")
Log.error("pkg-manager", f"安装失败 {plugin_name}: {type(e).__name__}: {e}")
if install_dir.exists():
shutil.rmtree(install_dir)
return False

View File

@@ -30,7 +30,8 @@ class EventBus:
for handler in handlers + wildcard_handlers:
try:
handler(event)
except Exception:
except Exception as e:
import traceback; print(f"[main.py] 错误:{type(e).__name__}:{e}"); traceback.print_exc()
pass
def on(self, event_type: str, handler: Callable):

View File

@@ -104,7 +104,7 @@ class PluginLoaderEnhancer:
try:
getattr(instance, method)()
except Exception as e:
ProLogger.error("safe", f"{name} {action}失败: {e}")
ProLogger.error("safe", f"{name} {action}失败: {type(e).__name__}: {e}")
self._on_plugin_error(name, info, str(e))
return
@@ -117,7 +117,7 @@ class PluginLoaderEnhancer:
info["info"].error_count = 0
ProLogger.info("safe", f"{name} {action}成功")
except Exception as e:
ProLogger.error("safe", f"{name} {action}失败: {e}")
ProLogger.error("safe", f"{name} {action}失败: {type(e).__name__}: {e}")
self._on_plugin_error(name, info, str(e))
def _on_plugin_error(self, name: str, info: dict, error: str):

View File

@@ -128,7 +128,7 @@ class ProPluginManager:
return instance
except Exception as e:
ProLogger.error("loader", f"加载失败 {plugin_dir.name}: {e}")
ProLogger.error("loader", f"加载失败 {plugin_dir.name}: {type(e).__name__}: {e}")
return None
def init_and_start_all(self):
@@ -160,7 +160,7 @@ class ProPluginManager:
info["info"].status = "initialized"
ProLogger.info("manager", f"已初始化: {name}")
except Exception as e:
ProLogger.error("manager", f"初始化失败 {name}: {e}")
ProLogger.error("manager", f"初始化失败 {name}: {type(e).__name__}: {e}")
info["info"].status = "error"
info["info"].error_count += 1
info["info"].last_error = str(e)
@@ -177,7 +177,7 @@ class ProPluginManager:
self._health_checker.add_plugin(name, instance)
ProLogger.info("manager", f"已启动: {name}")
except Exception as e:
ProLogger.error("manager", f"启动失败 {name}: {e}")
ProLogger.error("manager", f"启动失败 {name}: {type(e).__name__}: {e}")
info["info"].status = "error"
info["info"].error_count += 1
info["info"].last_error = str(e)
@@ -199,7 +199,7 @@ class ProPluginManager:
info["info"].status = "stopped"
ProLogger.info("manager", f"已停止: {name}")
except Exception as e:
ProLogger.warn("manager", f"停止异常 {name}: {e}")
ProLogger.warn("manager", f"停止异常 {name}: {type(e).__name__}: {e}")
def _on_plugin_failure(self, name: str):
"""插件失败回调"""
@@ -249,7 +249,7 @@ class ProPluginManager:
getattr(info["instance"], setter)(dep_instance)
ProLogger.info("inject", f"{name} <- {actual_dep}")
except Exception as e:
ProLogger.error("inject", f"注入失败 {name}.{setter}: {e}")
ProLogger.error("inject", f"注入失败 {name}.{setter}: {type(e).__name__}: {e}")
def _get_ordered_plugins(self) -> list[str]:
"""获取插件顺序"""

View File

@@ -29,7 +29,7 @@ class FallbackHandler:
self._cache[plugin_name] = result
return result
except Exception as e:
ProLogger.warn("fallback", f"插件 {plugin_name} 执行失败,触发降级: {e}")
ProLogger.warn("fallback", f"插件 {plugin_name} 执行失败,触发降级: {type(e).__name__}: {e}")
return self._apply_fallback(plugin_name)
def _apply_fallback(self, plugin_name: str) -> Any:
@@ -45,5 +45,5 @@ class FallbackHandler:
try:
return self.alternative_func()
except Exception as e:
ProLogger.error("fallback", f"备选方案也失败了: {e}")
ProLogger.error("fallback", f"备选方案也失败了: {type(e).__name__}: {e}")
return None

View File

@@ -46,7 +46,7 @@ class AutoRecovery:
return new_instance
except Exception as e:
ProLogger.error("recovery", f"恢复插件 {name} 失败: {e}")
ProLogger.error("recovery", f"恢复插件 {name} 失败: {type(e).__name__}: {e}")
self._recovery_attempts[name] = attempts + 1
return False

View File

@@ -55,7 +55,7 @@ class HealthChecker:
else:
self._failure_counts[name] = 0
except Exception as e:
ProLogger.error("health", f"插件 {name} 健康检查失败: {e}")
ProLogger.error("health", f"插件 {name} 健康检查失败: {type(e).__name__}: {e}")
self._on_failure(name)
def _on_failure(self, name: str):

View File

@@ -200,8 +200,16 @@ class PLInjector:
except SyntaxError as e:
Log.error("plugin-loader", f"插件 '{plugin_name}' PL/main.py 语法错误: {e}")
return False
except FileNotFoundError as e:
Log.error("plugin-loader", f"插件 '{plugin_name}' PL 文件不存在:{e}")
return False
except PermissionError as e:
Log.error("plugin-loader", f"插件 '{plugin_name}' PL 文件权限错误:{e}")
return False
except Exception as e:
Log.error("plugin-loader", f"加载插件 '{plugin_name}' 的 PL 失败: {e}")
Log.error("plugin-loader", f"加载插件 '{plugin_name}' 的 PL 失败{type(e).__name__}: {e}")
import traceback
traceback.print_exc()
return False
def _static_source_check(self, source: str, file_path: str):
@@ -371,15 +379,47 @@ class PluginManager:
with open(rf, "r", encoding="utf-8") as f: return f.read()
def _load_config(self, plugin_dir: Path) -> dict:
"""加载插件配置文件"""
cf = plugin_dir / "config.py"
if not cf.exists(): return {}
with open(cf, "r", encoding="utf-8") as f: content = f.read()
if not cf.exists():
return {}
try:
with open(cf, "r", encoding="utf-8") as f:
content = f.read()
except FileNotFoundError:
Log.warn("plugin-loader", f"配置文件不存在:{cf}")
return {}
except PermissionError as e:
Log.error("plugin-loader", f"配置文件无权限读取:{cf} - {e}")
return {}
except UnicodeDecodeError as e:
Log.error("plugin-loader", f"配置文件编码错误:{cf} - {e}")
return {}
# 安全检查
for p in ['import ', 'open(', 'exec(', 'eval(', 'os.', 'sys.', 'subprocess']:
if p in content: Log.warn("plugin-loader", f"{cf} 包含危险代码: {p}"); return {}
if p in content:
Log.warn("plugin-loader", f"{cf} 包含危险代码:{p}")
return {}
sg = {"__builtins__": {"True": True, "False": False, "None": None, "dict": dict, "list": list, "str": str, "int": int, "float": float, "bool": bool}}
lv = {}
try: code = compile(content, str(cf), "exec"); exec(code, sg, lv)
except Exception as e: Log.error("plugin-loader", f"配置文件解析失败: {e}"); return {}
try:
code = compile(content, str(cf), "exec")
exec(code, sg, lv)
except SyntaxError as e:
Log.error("plugin-loader", f"配置文件语法错误:{cf} - {e}")
return {}
except NameError as e:
Log.error("plugin-loader", f"配置文件名称错误:{cf} - {e}")
return {}
except TypeError as e:
Log.error("plugin-loader", f"配置文件类型错误:{cf} - {e}")
return {}
except Exception as e:
Log.error("plugin-loader", f"配置文件解析失败:{cf} - {type(e).__name__}: {e}")
return {}
return {k: v for k, v in lv.items() if not k.startswith("_") and not callable(v)}
def _load_extensions(self, plugin_dir: Path) -> dict:
@@ -470,7 +510,7 @@ class PluginManager:
try:
inst = self.load(lc_dir)
if inst: lifecycle_plugin = inst; self.plugins.pop("lifecycle", None)
except Exception: pass
except Exception as e: Log.warn("plugin-loader", f"lifecycle 插件加载失败:{type(e).__name__}: {e}")
dep_plugin = None
dep_dir = Path(store_dir) / "@{FutureOSS}" / "dependency"
@@ -478,7 +518,7 @@ class PluginManager:
try:
inst = self.load(dep_dir)
if inst: dep_plugin = inst; self._dependency_plugin = inst; self.plugins.pop("dependency", None)
except Exception: pass
except Exception as e: Log.warn("plugin-loader", f"dependency 插件加载失败:{type(e).__name__}: {e}")
sig_dir = Path(store_dir) / "@{FutureOSS}" / "signature-verifier"
if sig_dir.exists() and (sig_dir / "main.py").exists():
@@ -587,7 +627,7 @@ class PluginManager:
def stop_all(self):
for n, i in reversed(list(self.plugins.items())):
try: i["instance"].stop()
except Exception: pass
except Exception as e: Log.error("plugin-loader", f"插件 {n} 停止失败:{type(e).__name__}: {e}")
if self.lifecycle_plugin: self.lifecycle_plugin.stop_all()
def get_info(self, name: str) -> Optional[PluginInfo]:
@@ -635,4 +675,4 @@ register_plugin_type("PLInjector", PLInjector)
def New():
return PluginLoaderPlugin()
return PluginLoaderPlugin()

View File

@@ -124,7 +124,7 @@ class PluginStorage:
with open(file_path, mode, encoding="utf-8" if mode == "r" else None) as f:
return f.read()
except Exception as e:
Log.error("plugin-storage", f"读取文件失败 {self.plugin_name}/{path}: {e}")
Log.error("plugin-storage", f"读取文件失败 {self.plugin_name}/{path}: {type(e).__name__}: {e}")
return None
def write_file(self, path: str, content: str | bytes):
@@ -144,7 +144,7 @@ class PluginStorage:
with open(file_path, "w", encoding="utf-8") as f:
f.write(content)
except Exception as e:
Log.error("plugin-storage", f"写入文件失败 {self.plugin_name}/{path}: {e}")
Log.error("plugin-storage", f"写入文件失败 {self.plugin_name}/{path}: {type(e).__name__}: {e}")
def delete_file(self, path: str) -> bool:
"""删除插件目录内的文件"""
@@ -155,7 +155,7 @@ class PluginStorage:
return True
return False
except Exception as e:
Log.error("plugin-storage", f"删除文件失败 {self.plugin_name}/{path}: {e}")
Log.error("plugin-storage", f"删除文件失败 {self.plugin_name}/{path}: {type(e).__name__}: {e}")
return False
def list_files(self, prefix: str = "") -> list[str]:
@@ -176,7 +176,8 @@ class PluginStorage:
if f.is_file():
files.append(str(f.relative_to(self.data_dir)))
return sorted(files)
except Exception:
except Exception as e:
Log.error("plugin-storage", f"列出文件失败:{type(e).__name__}: {e}")
return []
def file_exists(self, path: str) -> bool:
@@ -184,7 +185,8 @@ class PluginStorage:
try:
file_path = self._resolve_path(path)
return file_path.exists() and file_path.is_file()
except Exception:
except Exception as e:
Log.error("plugin-storage", f"检查文件存在性失败:{type(e).__name__}: {e}")
return False
def serve_file(self, path: str) -> Response: