Bridge IPC 接口
window.qqqideBridge — preload 暴露给渲染层的全部 IPC 接口。
gaeaProcess — 进程管理
通用 process-type goods 进程管理。壳层 gaea-process.ts 实现。
// 启动进程
bridge.gaeaProcess.start(goodsId, scriptPath, runtime?, lifecycle?, allowMultiple?)
// → { ok: boolean, pid?: number, error?: string }
// 停止进程(taskkill /F /T 杀整棵进程树)
bridge.gaeaProcess.stop(goodsId)
// → { ok: boolean, error?: string }
// 查询状态
bridge.gaeaProcess.status(goodsId)
// → { running: boolean, pid?: number }
// 自启动偏好
bridge.gaeaProcess.getAutoStart(goodsId) // → boolean
bridge.gaeaProcess.setAutoStart(goodsId, v) // v: boolean
// 状态变更订阅(goods 专属 IPC channel)
bridge.gaeaProcess.onStatusChanged(cb) // → unsubscribe fn
start 参数
| 参数 | 类型 | 说明 |
|---|---|---|
goodsId | string | goods 唯一标识 |
scriptPath | string | 脚本路径,如 'goods/kope-a/q3.py' |
runtime | string | 'python' 或组件名。默认 'python' |
lifecycle | string | 'attached'(默认) / 'independent' |
allowMultiple | boolean | 允许并发多开(默认 false) |
脚本路径解析(四层 fallback)
① Data/webapp/<scriptPath> — 打包版,u 热更新优先
② resources/app/engines/<script> — 旧 r 兜底
③ server-app/<scriptPath> — 开发版
④ Data/webapp/<scriptPath> — 兜底(热更新后下次启动)
进程树清理
stop() → Windows: taskkill /F /T /PID <pid> (杀整棵树)
→ Unix: killpg (SIGTERM → 2s → SIGKILL)
主窗口退出 → cleanupAllGaeaProcesses() → 遍历所有 goods → stop()
/F 强制杀,/T 杀所有子进程(如 miniaudio 音频引擎)。
update — 热更新
bridge.update.check() // 检查更新 → { shell, webapp, ... }
bridge.update.apply() // 应用 webapp 更新
bridge.update.state() // 当前更新状态
bridge.update.abort() // 中止
bridge.update.upgradeShell() // 升级壳层
download — 文件下载
bridge.download.start(opts) // → { id }
bridge.download.cancel(id)
bridge.download.list() // → [{ id, url, progress, ... }]
bridge.download.onProgress(cb) // → unsubscribe fn
boot — 启动信息
bridge.boot.getInfo() // → { version, portableRoot, ... }
bridge.boot.retry() // 重试启动
bridge.boot.probe() // 探测
key — 全局快捷键
bridge.key.registerGlobal(accel, id)
bridge.key.unregisterGlobal(accel)
bridge.key.unregisterAllGlobal()
bridge.key.onGlobal(cb) // → unsubscribe fn
media — 媒体处理
bridge.media.thumb(opts) // 生成缩略图
bridge.media.transcode(opts) // 转码
bridge.media.probe(src) // 探测元信息
bridge.media.ffmpegPath() // → ffmpeg 路径
audio — 统一音频机器(2026-08-06)
bridge.audio.play(file, opts?) // 播放。opts: { volume: 0.0-1.0 }
bridge.audio.stop(scope?) // 停止。'music' / 'clipboard' / 默认 all
bridge.audio.invoke(action, params) // 透传引擎动作(play_music/play_radio 等)
bridge.audio.isAlive() // 引擎存活 → boolean
file 路径解析:'yz:<name>' → webapp/assets/yz/ · 'assets/<rel>' → webapp/ · 绝对路径原样。
引擎:主进程 AudioEngine → miniaudio AudioHub(24 并发 SFX 池 + 解码缓存 + 静音修剪)。详参 audio-api.md
shell — 系统集成
bridge.shell.openPath(p) // 打开文件/目录(系统资源管理器)
bridge.shell.openExternal(url) // 外部浏览器
bridge.shell.openTerminal(p, type) // 当前目录打开终端。type: 'cmd' | 'powershell'
bridge.shell.openRecycleBin() // 打开回收站(explorer shell:RecycleBinFolder)
bridge.shell.hardRefresh() // 强制刷新
bridge.shell.onBrowserFallback(cb) // 浏览器启动兜底通知 → unsubscribe fn
kope — 剪贴板历史 goods(2026-07)
bridge.kope.getHistory(limit, offset, keyword?) // → [{id, content, content_hash, preview, size_bytes, content_type, pinned, pinned_at, created_at, updated_at}]
bridge.kope.getStats() // → { total, pinned, max_updated_at }
bridge.kope.togglePin(id) // → boolean(钉住/取消钉住)
bridge.kope.deleteItem(id) // → boolean
存储:%LOCALAPPDATA%/kope-a/kope.sq3(OS 级唯一真理源)。
双写者并发模型(kope 独有,值得抄)
q3.py (Python) → kope_store.py (sqlite3) → 仅 INSERT 新剪贴板条目
panel.html (JS) → bridge.kope.* → sql.js → SELECT / UPDATE / DELETE
WAL 模式天然并发安全:Python 只 INSERT,JS 只查改删。JS 每次写前从磁盘重读(_reloadIfChanged),防覆盖 Python 刚写入的新条目。
OS 级 sql.js 库强制规范(kope/roam 通用)
- 落盘:tmp + rename 原子替换,写前 copy 当前文件为
.prev(保留上一完好版) - 加载三级恢复链:主文件 →
.prev→ 重建空库,绝不让损坏库继续跑 - 外部修改守卫:落盘前磁盘 mtime 更新且磁盘行数更多 → 以磁盘为准 reload,不覆盖
- 单例锁:
.singleton.lock(OS 级互斥);跨实例状态:.gaea-state.json(10s 心跳 / 30s 过期) - 迁移/外部回写 goods 库前必须先停 goods 进程(查 .gaea-state.json 确认 PID 不存活)
roam — OS 级资源管理器持久化(2026-08-03)
bridge.roam.get(key) // → value
bridge.roam.set(key, value)
bridge.roam.getAll() // → { key: value }
bridge.roam.onChanged(cb) // → unsubscribe。跨窗口广播 {key, value}
存储:%LOCALAPPDATA%/qqqide/roam.sq3,整操作系统唯一真理源,多窗口事件驱动秒级同步。