跳转到内容

下载 Termii · v0.4.5

三分钟,装进你的 Dock

原生构建,包体仅数 MB。应用内自动更新,始终新鲜。

安装说明

macOS:若提示「无法打开」,在终端执行 xattr -dr com.apple.quarantine /Applications/Termii.app。Windows:首次运行可能触发 SmartScreen,选择「仍要运行」即可。

插件服务总线与依赖

插件之间的协作走服务总线(ctx.plugins),而不是互相 import 代码: Snippets 之于 BatchTasks 这类「功能复用功能」的场景,调用方与被调方通过 注册表路由,彼此故障隔离。

plugins: {
expose(service: string, handler: (method: string, params: unknown) => unknown): Disposer;
invoke<T>(pluginId: string, service: string, method: string, params?: unknown): Promise<T>;
isActive(pluginId: string): boolean;
}
  • expose:注册本插件的一个服务。返回 Disposer,插件去激活时服务自动 摘除;同插件内服务名冲突时拒绝后注册者。
  • invoke:只允许调用**已启用(active)**插件;目标插件未启用 / 未 expose 该服务 / 不存在 → reject 明确错误。被调方 handler 抛错 → reject (故障隔离,不中断调用方)。调用发起时会先等待启动加载收尾,消除 「插件存在但尚未加载」的启动竞态。
  • isActive:目标插件当前是否已激活(同步返回,不触发加载)。可选依赖 探测专用。
// 提供方(termii-snippets 内部):暴露 "snippets" 服务
ctx.plugins.expose("snippets", (method, params) => {
if (method === "list") return listSnippets();
throw new Error(`unknown method: ${method}`);
});
// 消费方(termii-batch 的现网写法):调用 snippets 的 list 方法
const list = await ctx.plugins.invoke<SnippetSummary[]>(
"termii-snippets",
"snippets",
"list"
);
// SnippetSummary { id, name, group?, command, variables: string[] }
// variables:命令模板里的 {{name}} 占位符名,保留首次出现顺序

建议约定:method 用动词(list / get / save / run…),params 传 JSON 可序列化数据,错误一律 throw new Error(会带上调用方上下文 透传)。

依赖声明(dependencies / optionalDependencies)

Section titled “依赖声明(dependencies / optionalDependencies)”

在 plugin.json 里声明后,宿主按依赖拓扑序加载:先依赖、后使用方, 保证使用方 activate 时依赖已激活、服务可调。

{ "dependencies": ["termii-snippets"] }

依赖不可达(未安装 / 未启用 / 未信任 / 加载失败 / 存在循环)时:

  • 本插件跳过加载,跳过原因显示在「设置 → 插件」与加载日志中;
  • 其余插件不受影响;启用时也会被宿主拦截并 toast 提示 「请先启用并信任:…」。
{ "optionalDependencies": ["termii-tunnels"] }
  • 宿主只做「尽力序」:可选依赖在候选集内(已安装且已启用且已信任)时 优先于使用方加载(保证激活期即可用 isActive 探测到)。
  • 缺失 / 加载失败不跳过本插件——由插件运行时自检并降级:
if (ctx.plugins.isActive("termii-snippets")) {
const list = await ctx.plugins.invoke("termii-snippets", "snippets", "list");
} else {
// 降级:隐藏「片段」来源
}

宿主自身也会经服务总线转发部分能力,最典型的是 ctx.tunnels.saveRule: 它把规则保存转发给官方插件 termii-tunnels 的 "tunnels" 服务 (目标插件未启用时 reject):

await ctx.tunnels.saveRule(rule); // 新增或更新一条规则(只落库,不启动)

官方插件的真实协作:termii-snippets 暴露 "snippets" 服务, termii-batch 声明 optionalDependencies: ["termii-snippets"], 激活时用 ctx.plugins.isActive 探测,可用则拉取片段列表作为批量任务的 命令来源。这是「功能复用功能」的参考实现。