PluginContext API 参考
PluginContext API 参考
Section titled “PluginContext API 参考”activate(ctx) 收到的 ctx 是插件与宿主之间的唯一边界。本节给出完整
签名(与宿主 src/lib/plugins/types.ts 对齐,SDK 自动生成同形类型)。
| 成员 | 类型 | 说明 |
|---|---|---|
ctx.pluginId |
readonly string |
当前插件 id |
ctx.apiVersion |
readonly number |
宿主支持的插件 API 版本(当前 3,= SUPPORTED_API_VERSION) |
ctx.ui |
object | 贡献点注册 + toast / modal / navigate |
ctx.plugins |
object | 插件服务总线(expose / invoke / isActive) |
ctx.terminal |
object | 终端 pane 读写与输出订阅 |
ctx.sessions |
object | 终端会话创建原语 |
ctx.process |
object | 本地流式进程(L1 process) |
ctx.hosts |
object | 主机连接 / 执行 / 本机执行 |
ctx.tunnels |
object | 端口转发(隧道) |
ctx.dialog |
object | 原生对话框(含目录选择) |
ctx.fs |
object | 受限文件写 |
ctx.vault |
object | 凭证保险库(keyring),批量能力需 L1 |
ctx.config |
object | 配置快照导出/导入(L1 process) |
ctx.paths |
object | 应用路径投影 |
ctx.sftp |
object | 文件传输(同步形态) |
ctx.sidecar |
object | 原生能力桥(L1 sidecar) |
ctx.storage |
object | 插件私有持久化 KV |
ctx.events |
object | Tauri 事件订阅(白名单) |
ctx.i18n |
object | 文案注册 / 语言读取与监听 |
ui — 贡献点注册
Section titled “ui — 贡献点注册”所有注册方法都返回 Disposer(() => void),插件去激活时宿主统一回放。
registerView — 视图
Section titled “registerView — 视图”ctx.ui.registerView(view: ViewContribution): Disposer;// ViewContribution {// id: string; // 必须以 "<pluginId>." 开头// icon: PluginIcon; // lucide 图标组件// labelKey: string; // 文案键,默认在 "views" 命名空间解析// ns?: string; // i18n 命名空间,缺省 "views"// component: ComponentType;// }侧栏条目 + 主区组件。注册后自动获得 ⌘1..9 快捷键与命令面板入口(都从 可见侧栏派生)。
registerCommand — 命令
Section titled “registerCommand — 命令”ctx.ui.registerCommand(cmd: CommandContribution): Disposer;// CommandContribution {// id: string;// group: string; // 分组标题(已本地化的展示字符串)// title: string;// sub?: string;// icon: PluginIcon;// run: () => void | Promise<void>;// }⌘K 命令面板条目。
registerSettingsSection — 设置分区
Section titled “registerSettingsSection — 设置分区”ctx.ui.registerSettingsSection(section: SettingsSectionContribution): Disposer;// SettingsSectionContribution {// id: string;// icon: PluginIcon;// labelKey: string; // 默认在 "settings" 命名空间解析// ns?: string; // 缺省 "settings"// component: ComponentType;// }设置页新分类。
registerShortcut — 全局快捷键
Section titled “registerShortcut — 全局快捷键”ctx.ui.registerShortcut(shortcut: ShortcutContribution): Disposer;// ShortcutContribution {// id: string;// combo: string; // 如 "Mod+Shift+D"// run: () => void;// }combo 语法:Mod = ⌘(macOS) / Ctrl(其他),Cmd / Ctrl 是同义词;
Shift / Alt 可选;最后一段为单字符键;大小写不敏感。内置快捷键
(⌘K / T / W / D、⌘0..9)优先命中,未处理的按键才落到插件快捷键表。
registerTheme — 应用主题
Section titled “registerTheme — 应用主题”ctx.ui.registerTheme(theme: ThemeContribution): Disposer;// ThemeContribution {// id: string;// label: string; // 主题卡片显示名(纯文本,自行本地化)// dark: boolean; // 暗色主题标记// previewBg?: string; // 卡片预览色;缺省取 vars 里的 --bg / --fg// previewFg?: string;// vars: Record<string, string>; // CSS 自定义属性(-- 开头),经消毒注入// }注入 :root[data-theme="<id>"] { …vars }。消毒规则:键必须 -- 开头、
不允许 {} / ;;值不允许 {} / </style;违规声明被静默丢弃。
registerTrayItem — 托盘项
Section titled “registerTrayItem — 托盘项”ctx.ui.registerTrayItem(item: TrayItemContribution): Disposer;// TrayItemContribution {// id: string;// label: string; // 菜单显示文本(纯文本,自行本地化)// run: () => void;// }系统托盘右键菜单固定区条目(「新建本地终端」与「SSH 主机」子菜单之后),
经 tray://plugin-item 事件分发触发。
ui.toast — 通知
Section titled “ui.toast — 通知”ctx.ui.toast.success(opts: { title: string; description?: string }): string;ctx.ui.toast.error(opts: { title: string; description?: string }): string;ctx.ui.toast.info(opts: { title: string; description?: string }): string;返回 toast id。
ctx.ui.toast.running(opts: { title: string; description?: string; progress?: { total: number; completed: number; stage: string }; // total 为 0 → indeterminate}): string; // 持续 toast(不自动消失),结束时用 update 切换
ctx.ui.toast.update(id: string, patch: { kind?: "success" | "error" | "info" | "running"; title?: string; description?: string; duration?: number; // 自动消失时长(ms) progress?: { total; completed; stage } | null; // null 显式清空进度条}): void;典型流程见 界面反馈与文案。
ui.modal — 弹窗
Section titled “ui.modal — 弹窗”ctx.ui.modal.confirm(opts: { title: string; body?: string; confirmText?: string; cancelText?: string; danger?: boolean; // 红色确认按钮}): Promise<boolean>;
ctx.ui.modal.alert(opts: { title: string; body?: string }): Promise<void>;
ctx.ui.modal.openForm(opts: { title: ReactNode; body: ReactNode; // 任意 ReactNode,弹窗栈顶层入口 footer?: ReactNode; // 底部槽位;null → 空 .dlg-footer 容器(ModalFooter portal 渲染按钮)}): void;
ctx.ui.modal.close(): void; // 关闭当前最顶层弹窗
ctx.ui.modal.setCancelable(cancelable: boolean): void; // Esc / 遮罩关闭守卫(仅 form 弹窗)ui.navigate — 视图导航
Section titled “ui.navigate — 视图导航”ctx.ui.navigate(viewId: string): void;切换主区视图(核心视图 id 或插件视图 id)。
plugins — 服务总线
Section titled “plugins — 服务总线”ctx.plugins.expose( service: string, handler: (method: string, params: unknown) => unknown): Disposer; // 注册本插件的一个服务;去激活自动摘除
ctx.plugins.invoke<T>( pluginId: string, service: string, method: string, params?: unknown): Promise<T>; // 只允许调用已启用(active)插件;故障隔离
ctx.plugins.isActive(pluginId: string): boolean; // 同步探测,不触发加载详见 插件服务总线与依赖。
terminal — 终端
Section titled “terminal — 终端”ctx.terminal.getActivePane(): ActivePaneInfo | null;// ActivePaneInfo { paneId: string; kind: "local" | "ssh" | "serial"; backendId: string }// 预览等非终端 pane 返回 null
ctx.terminal.writeActive(text: string): Promise<boolean>; // 写入并聚焦活跃 panectx.terminal.writePane(paneId: string, text: string): Promise<boolean>;// 写入指定 pane(不在活跃 tab 也能写);pane 不存在 / 写入失败 → false
ctx.terminal.focusActive(): void;
ctx.terminal.onOutput(cb: (chunk: OutputChunk, pane: ActivePaneInfo) => void): Disposer;// OutputChunk { seq: number; data: string };订阅活跃 pane 输出流,切换自动跟随sessions — 终端会话创建
Section titled “sessions — 终端会话创建”ctx.sessions.openLocalTab(): Promise<string | null>; // 新开本地终端 tab,返回 paneIdctx.sessions.openHostTab(hostId: string): Promise<string | null>; // 新开 SSH tab(自动确保连接在线)ctx.sessions.focus(paneId: string): void; // 聚焦 pane(切换所在 tab 为活跃)process — 本地流式进程
Section titled “process — 本地流式进程”ctx.process.spawn( cmd: string, args: string[], opts?: { cwd?: string; env?: Record<string, string> }): Promise<ProcessHandle>;// 需要 L1 `process` 能力;argv 方式(不做 shell 展开)interface ProcessHandle { readonly id: string; write(data: string): Promise<void>; // 写入 stdin kill(): Promise<void>; // 终止子进程 onData(cb: (chunk: ProcChunk) => void): Disposer; // ProcChunk { seq: number; data: string; stream: "stdout" | "stderr" } onExit(cb: (info: { code: number | null; error?: string }) => void): Disposer; // code 为 null 表示被终止 / 传输中断,error 给出原因}插件去激活时其全部进程被宿主强制回收(孤儿防护)。
hosts — 主机
Section titled “hosts — 主机”ctx.hosts.list(): readonly HostSummary[];// HostSummary { id, name, host, port, username, group?, tags: string[], favorite }// 只读投影,不含任何凭证字段
ctx.hosts.connect(hostId: string): Promise<string>; // 建立(或复用)连接,返回 sessionIdctx.hosts.exec(hostId, command: string, opts?: { timeoutSecs?: number }): Promise<{ stdout: string; stderr: string; exitCode: number }>;ctx.hosts.disconnect(hostId: string): Promise<void>;ctx.hosts.reconnect(hostId: string): Promise<string>; // 重建 transport,返回新 sessionIdctx.hosts.execLocal(command: string, opts?: { timeoutSecs?: number }): Promise<{ stdout: string; stderr: string; exitCode: number }>;// 本机执行(临时 PTY 只收集 stdout,stderr 恒为空串;默认超时 60s)
ctx.hosts.execStream(hostId: string, command: string): Promise<ProcessHandle>;// SSH exec 通道流式执行;需要 L1 `process`;kill() 关闭通道终止远端进程tunnels — 隧道(端口转发)
Section titled “tunnels — 隧道(端口转发)”ctx.tunnels.list(hostId?: string): Promise<PluginForwardInfo[]>;// PluginForwardInfo = ForwardInfo & { hostId: string }// 缺省 hostId → 所有主机的转发;给 hostId → 只返回该主机名下的
ctx.tunnels.start(hostId: string, spec: ForwardSpec): Promise<ForwardInfo>;// ForwardSpec { kind: "local" | "remote" | "dynamic"; bindHost; bindPort; targetHost; targetPort }// 自动确保 SSH transport 在线
ctx.tunnels.stop(hostId: string, forwardId: string): Promise<void>;ctx.tunnels.probeRemote(hostId: string, bindHost: string): Promise<RemoteForwardProbe>;// 探测远端 sshd 是否会在 -R 转发时尊重 bindHost(启动 -R 前调用)
ctx.tunnels.applyRemoteConfig(hostId: string): Promise<void>;// 把远端 GatewayPorts 翻成 clientspecified 并 reload sshd(需 NOPASSWD sudo)
ctx.tunnels.onChanged(cb: (hostId: string) => void): Disposer; // 订阅隧道增删变更
ctx.tunnels.saveRule(rule: TunnelRule): Promise<void>;// 保存(新增或更新)隧道规则,经服务总线转发给 termii-tunnels 的 "tunnels" 服务;// 只落库不启动;目标插件未启用 → rejectdialog — 原生对话框
Section titled “dialog — 原生对话框”ctx.dialog.pickSavePath(opts?: { defaultName?: string; extensions?: string[]; // 文件类型过滤(不含前导点、小写,如 ["tar"])}): Promise<string | null>; // 取消返回 null;选中的路径在本次会话内可被 fs.writeText 写入
ctx.dialog.pickFile(opts?: { extensions?: string[] }): Promise<string | null>;
ctx.dialog.pickDirectory(): Promise<string | null>; // 取消返回 nullfs — 受限文件写
Section titled “fs — 受限文件写”ctx.fs.writeText(path: string, content: string): Promise<void>;// 仅允许写本次会话内经 ctx.dialog.pickSavePath 返回的路径;未授权 → 抛错vault — 凭证保险库
Section titled “vault — 凭证保险库”ctx.vault.get(id: string): Promise<string | null>; // 不存在返回 nullctx.vault.set(id: string, secret: string): Promise<void>;ctx.vault.delete(id: string): Promise<void>; // 不存在时静默成功
// 批量能力:需要 L1 `process`ctx.vault.list(): Promise<string[]>;ctx.vault.export(): Promise<Record<string, string>>;ctx.vault.import(entries: Record<string, string>): Promise<void>; // 整体替换按 id 的 get/set/delete 无能力门禁(vault 与 hosts / tunnels /
sessions 同属核心服务投影);list/export/import 涉及全量凭据,纳入
L1 process 信任锁。
config — 配置快照
Section titled “config — 配置快照”ctx.config.export(): Promise<string>; // 当前完整配置快照(JSON 字符串)ctx.config.import(json: string): Promise<void>; // 应用快照并立即落盘需要 L1 process 能力。导出内容包含 hosts / settings / pluginSettings /
layouts;导入会复用启动时的迁移/归一化逻辑并更新当前运行中的 store,
供配置同步类插件使用。
paths — 应用路径
Section titled “paths — 应用路径”ctx.paths.appDataDir(): Promise<string>; // config.json 与 plugins/ 所在目录sftp — 文件传输
Section titled “sftp — 文件传输”ctx.sftp.upload( hostId: string, localPath: string, remotePath: string, onProgress?: (p: { transferred: number; total: number }) => void): Promise<void>;ctx.sftp.download( hostId: string, remotePath: string, localPath: string, onProgress?: (p: { transferred: number; total: number }) => void): Promise<void>;同步形态:Promise 在传输完成 / 失败后才 settle。内部使用主机的文件
SSH 会话(与 hosts.exec 的 terminal 会话分离)。total 在传输开始后
可能为 0(总大小未知)。错误消息透传 sftp 命令的原始错误。
sidecar — 原生能力桥
Section titled “sidecar — 原生能力桥”ctx.sidecar.call<T = unknown>( method: string, params?: unknown, timeoutMs?: number // 默认 10000): Promise<T>;需要 L1 sidecar(隐含 process)。错误分支见
流式进程与 sidecar。
storage — 持久化 KV
Section titled “storage — 持久化 KV”ctx.storage.get<T>(key: string, fallback: T): T; // 同步读,缺省返回 fallbackctx.storage.set(key: string, value: unknown): void;落在 config.json 的 settings.pluginSettings.<pluginId>,按插件隔离。
events — 事件订阅
Section titled “events — 事件订阅”ctx.events.listen(event: string, cb: (payload: unknown) => void): Disposer;白名单前缀(白名单外订阅被拒绝并打印错误):
pty:// sshch:// serial:// ssh:// transfer://fs-progress:// tray:// forward:// proc://i18n — 文案与语言
Section titled “i18n — 文案与语言”ctx.i18n.addBundle(lang: string, ns: string, resources: Record<string, unknown>): void;// ns 被强制改写为 "plugin-<pluginId>"(传什么都一样,避免覆盖宿主命名空间);深合并
ctx.i18n.getLanguage(): string; // "en-US" / "zh-CN"ctx.i18n.onLanguageChanged(cb: (lng: string) => void): Disposer;