@wegirl/sdk 唯一通道规范(宿主能力接入铁律)
版本:2026-09-14 起 生效 · 真相源:宿主
src/plugins/hostSdk.js(createHostSdk)+plugins/scripts/shims/sdk.js(编译器 shim)+electron/plugins/build-lib.cjs(SHIMS + 构建守卫) 本文是插件访问宿主能力的唯一规范;API 逐项细节见PLUGIN_DEVELOPMENT.md§8。
1. 铁律:只有一种方式
插件源码访问宿主能力,只允许经 @wegirl/sdk 导入。
// ✅ 唯一正确姿势(推荐默认导入——永不怕 shim 导出面滞后)
import sdk from '@wegirl/sdk';
const { useModal, actions, wegirlFetch } = sdk;
// ✅ 具名导入也可以(shim 已列出的稳定字段)
import { useModal, getDesktopDashboardState, actions } from '@wegirl/sdk';
禁止清单(宿主构建期守卫会扫描并告警/报错):
| 禁止写法 | 是什么 | 应改为 |
|---|---|---|
window.__WEGIRL__ / globalThis.__WEGIRL__ |
宿主运行时内部交接点(react/sdk/cap/ui/editors/panels) | 一律 @wegirl/sdk;editors/panels 也在 sdk.editors / sdk.panels 上 |
window.api.* / globalThis.api.* |
preload 原生桥(IPC 通道裸面) | sdk.fs / sdk.invoke / sdk.app / getCapability(...) 等语义化能力 |
运行时兜底 globalThis.__WEGIRL__?.sdk |
旧编译器 shim 缺导出时的历史绕行(cross-border 插件曾用) | 已废除。升级编译器包即可;shim 默认导出永远指向运行时最新 sdk 单例,不存在滞后 |
__WEGIRL__ 全局只允许出现在宿主自有代码里(hostRuntime 注入 + shim 文本),它是宿主实现细节,不是插件 API。
2. 为什么默认导入优先
shim 的具名导出是构建期快照(export const useModal = sdk.useModal),编译器包落后于宿主时新字段拿不到;而 export default sdk 是对运行时单例的直通引用——宿主加什么能力,sdk.xxx 立即可用,升级宿主不需要升级编译器。
结论:默认导入为主,具名导入仅用于 shim 清单里明确列出的字段(清单见 PLUGIN_DEVELOPMENT.md §8.2.1)。
3. 常用能力速查
| 需求 | 写法 |
|---|---|
| 当前项目(快照) | sdk.getCurrentProject()(回调/事件里用;宿主已封装本地 find + 云端回退) |
| 当前项目(响应式) | const project = sdk.useCurrentProject()(组件里用,切换项目自动重渲染) |
| 响应式读状态 | sdk.useDesktopDashboardStore(s => ...) |
| 打开编辑器条目 | sdk.actions.openEditorItemForProject(projectId, node) |
| 打开/关闭文件 | sdk.actions.openAndLoadFile(projectId, node) / closeFileForProject |
| 调用插件主进程 | sdk.invoke(pluginId, method, payload)(桌面 IPC / 云端代理自动路由) |
| 调用主进程 cap(原样信封) | sdk.getCapability(capId).method(...) |
| 调用主进程 cap(解包+抛错) | await sdk.callCap(capId, method, payload)(SDK 内置,推荐) |
| 订阅主进程推送事件 | sdk.events.on(channel, cb)(返回解绑函数;webContents.send 的通道) |
| 直发网关 REST(带宿主鉴权) | sdk.wegirlFetch(url, { skipErrorModal: true }) |
| 模块化网关请求(R 解包) | sdk.apiClient.get/post/postForm(module, path, opts) |
| 弹窗 | sdk.useModal / sdk.showModal / sdk.showConfirmModal |
| 宿主编辑器组件 | sdk.editors.EditorShell / sdk.editors.DesktopImagePreview …(活 getter) |
| 宿主面板组件 | sdk.panels(活 getter) |
| AI 行动按钮 | sdk.AIButton(旧名 SparkleButton 为兼容别名) |
| 文件读写 | sdk.fs.readFile / writeFile / exists / remove |
| 图片查看器 | sdk.app.openImageViewer(payload) |
| 插件热重载 | sdk.reloadPlugin(pluginId) |
4. 获取「当前项目」标准范式
首选宿主封装好的派生 getter(本地 find + 云端回退规则在宿主侧维护,插件不必了解 store 形状):
import sdk from '@wegirl/sdk';
// 回调 / 事件里(非响应式快照):
const project = sdk.getCurrentProject();
const projectId = project?.id || '';
// 组件里(响应式 hook,切换项目自动重渲染):
const project = sdk.useCurrentProject();
需要项目以外的 store 字段时才下沉到原始 store 访问:
const st = sdk.getDesktopDashboardState(); // 快照
const v = sdk.useDesktopDashboardStore(s => s.xxx); // 响应式
云端项目注意:
selectedProjectId会被置为云端项目 id,但projects数组里没有云端项目对象,宿主的getCurrentProject/useCurrentProject已内建回退selectedCloudProject,不要再手写这段逻辑。
5. 构建期守卫
宿主 build-lib.cjs 的 hostGlobalsGuardPlugin 会扫描插件源码(shim 文本不在扫描范围):
- 命中
__WEGIRL__或window.api / globalThis.api→ 逐点告警(含 文件:行:列)。 - severity 由构建入口配置:
'warn'(默认,存量过渡)|'error'(构建失败)|'off'。 - 存量插件清理完成后建议宿主切到
'error',让铁律可执行。
6. 存量代码迁移对照表
| 旧写法(已废除) | 新写法 |
|---|---|
const sdk = globalThis.__WEGIRL__?.sdk |
import sdk from '@wegirl/sdk' |
window.__WEGIRL__?.editors |
sdk.editors |
window.__WEGIRL__?.panels |
sdk.panels |
window.__WEGIRL__?.actions(宿主本就无此字段,恒 null) |
sdk.actions |
window.api.plugins.invoke(id, method, payload) 兜底 |
sdk.invoke(id, method, payload)(桌面/云端已自动路由,无需兜底) |
window.api.desktop.readFile |
sdk.fs.readFile |
window.api.cap.callCap(...) |
sdk.callCap(capId, method, payload)(SDK 内置)或 sdk.getCapability(capId).method(...) |
7. 适配本规范的宿主侧配套(2026-09-14)
hostSdk.js:新增editors/panels活 getter——插件不再有任何「必须直读__WEGIRL__」的理由。build-lib.cjsSHIMS:@wegirl/sdk补editors/panels/AIButton导出;默认导出早已存在。- 编译器 shim(
plugins/scripts/shims/sdk.js→ CDN 编译器包):同步以上导出,header 注明本铁律。