架构概览
PyriteIDE 的技术架构、进程模型与插件运行时。
PyriteIDE 是基于 Flutter 的跨平台 MicroPython IDE,桌面(Windows、Linux、macOS)与 Android 使用同一套核心架构。
技术栈
| 层级 | 技术 |
|---|---|
| UI 框架 | Flutter (Dart) |
| 插件运行时 | Python(内嵌,serious_python) |
| 插件通信 | PythonBridge(进程内通道) |
| 视图渲染 | 原生渲染器(native.*)+ 快照/补丁协议 |
架构分层
┌─────────────────────────────────────────┐
│ Flutter UI Layer │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Editor │ │ File │ │ Device │ │
│ └─────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────┤
│ Core Services │
│ ┌─────────┐ ┌──────────┐ ┌──────────┐ │
│ │ File │ │ Editor │ │ Git │ │
│ │Provider │ │ Provider │ │ Provider │ │
│ └─────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────┤
│ Python Runtime Layer │
│ ┌──────────────────────────────────┐ │
│ │ PythonRuntimeHost (单例解释器) │ │
│ │ ┌────────┐ ┌─────────────┐ │ │
│ │ │Bridge │ │ Plugin A/B/C│ │ │
│ │ │(PB) │ │ (Python) │ │ │
│ │ └────────┘ └─────────────┘ │ │
│ └──────────────────────────────────┘ │
└─────────────────────────────────────────┘核心模块
lib/app/
应用启动、路由配置、全局 Provider。
lib/core/
共享模型、服务、SDK API、常量和持久化。
| 子目录 | 说明 |
|---|---|
services/ | 核心业务逻辑(file、editor、git、device 等) |
models/ | 数据模型 |
providers/ | Riverpod Provider |
sdk/ | 插件运行时宿主、Manifest 校验、PythonBridge 传输、运行时启动 |
i18n/ | 国际化支持 |
lib/pages/
功能页面:editor、files、git、plugins、settings、device-tools。
lib/shared/ 与 lib/features/
可复用 UI 组件与功能模块(features/plugin_view/ 含原生组件渲染器,如 PluginVideoPlayer)。
Python 运行时模型
与传统的“每个插件一个子进程”不同,PyriteIDE 使用单例 Python 解释器:
- 所有插件运行在同一个内嵌 Python 解释器中(经
serious_python嵌入 IDE 进程)。 - 启动时先
boot.py引导运行时,再逐个加载插件__main__.py。 - 插件之间的通信与数据通过
PythonBridge的按插件隔离的 channel 进行,标签形如pyrite.plugin.<pluginId>.<sessionId>(Data 插件追加.once)。 PythonRuntimeHost负责启动、停止、重启插件会话,并为每个 session 生成sessionId与generation。
PythonBridge 传输
- 通信发生在 IDE 进程内,不依赖 WebSocket / 网络套接字。
- 协议版本通过 capability 协商:宿主能力为
sdk.v1。 - 每个插件会话通过环境变量获得自己的 channel:
PYRITE_IDE_PLUGIN_BRIDGE_PORT、PYRITE_IDE_PLUGIN_BRIDGE_LABEL、PYRITE_IDE_DART_SESSION_TOKEN,以及运行时派生的PYRITE_IDE_PLUGIN_ID、_SESSION_ID、_GENERATION、_PLUGIN_DIR、_DATA_DIR、_CACHE_DIR、_TEMP_DIR、_PLUGIN_CAPABILITIES等。 - 所有消息使用协议 v1 与 session/generation 校验。
线程规则
- Python 解释器在 IDE 进程内的专用运行时线程上执行。
- SDK 回调在 Bridge 线程上执行,不在 Flutter 主线程。插件回调因此不能直接触碰 UI;对 UI 的操作通过
ide.view.*事件帧/快照同步回 Flutter。 - Flutter 侧的事件(
ide.view.event、ide.view.ack/nack/resync、ide.event.emit、ide.view.route.sync等)在收到后路由到对应 session。
单例解释器约束
因为所有插件共享一个解释器:
- 全局状态(模块级单例、
sys.path、运行时代理)在插件之间共享,插件应使用插件ID.前缀命名空间来避免冲突。 - 一个插件若未正确退出(保留存活的后端目标),会导致该插件无法再次启停,必须“重启运行时”才会整体恢复。
- Data 插件使用
run_once()在贡献后自动退出,避免占用解释器。 - 重启运行时(硬件复位或显式重启)会
reset整个解释器并递增generation,所有已有 session 被拆除;此前创建的运行时引用全部失效(抛出StaleReferenceError)。
生命周期
install → start (session, generation++) → ready
→ dispose → stopped
Data: start → on_contribute → run_once() → auto-exitrestartRuntime() 会先 stopAll(),重置解释器并递增 generation,随后可按激活事件重新启动插件。