Skip to main content

zerolaunch_plugin_protocol/
manifest.rs

1use serde::{Deserialize, Serialize};
2use zerolaunch_plugin_api::PluginMode;
3
4/// 顶层插件 manifest,从 `manifest.toml` 反序列化,也可序列化为 JSON 返回给前端。
5#[derive(Debug, Clone, Serialize, Deserialize)]
6pub struct Manifest {
7    /// 插件元信息(ID、名称、版本、作者等)
8    #[serde(rename = "plugin")]
9    pub plugin: PluginSection,
10    /// 运行时配置(启动命令、超时、自动重启策略)
11    #[serde(default, rename = "runtime")]
12    pub runtime: RuntimeSection,
13    /// 组件声明(插件对外提供哪些能力)
14    #[serde(default, rename = "components")]
15    pub components: ComponentsSection,
16    /// 前端 UI 入口(第三方插件可选的 Vue 面板)
17    #[serde(default, rename = "ui")]
18    pub ui: Option<UiSection>,
19    /// 插件图标文件路径
20    #[serde(default, rename = "icon")]
21    pub icon: Option<IconSection>,
22}
23
24/// 插件元信息段。
25#[derive(Debug, Clone, Serialize, Deserialize)]
26pub struct PluginSection {
27    /// 插件唯一标识,反向域名格式,如 `com.example.my-plugin`
28    #[serde(rename = "id")]
29    pub id: String,
30    /// 显示名称
31    #[serde(rename = "name")]
32    pub name: String,
33    /// 语义版本号
34    #[serde(rename = "version")]
35    pub version: String,
36    /// 简短描述
37    #[serde(rename = "description")]
38    pub description: String,
39    /// 作者名
40    #[serde(rename = "author")]
41    pub author: String,
42    /// 插件形态:`inline`(行内,触发词路由)或 `panel`(独立插件,候选项/热键唤醒)
43    #[serde(rename = "mode")]
44    pub mode: PluginMode,
45    /// 全局唤醒快捷键(如 `Ctrl+E`)。可空;仅 `panel` 形态注册热键
46    #[serde(default, rename = "hotkey")]
47    pub hotkey: Option<String>,
48    /// 触发关键词;`panel` 形态下作为默认候选项的匹配关键字。
49    /// 行内插件默认按"触发词 + 空格"路由;插件可在代码中覆盖 `Plugin::match_query` 自定义判定。
50    #[serde(rename = "triggerKeywords")]
51    pub trigger_keywords: Vec<String>,
52    /// 动态触发说明(可选):无触发词、由 `Plugin::match_query` 自定义判定的行内插件,
53    /// 用一句自然语言说明满足什么形态的输入会被命中(如"输入形如网址时")。
54    /// 仅用于设置页展示(解释该插件为何没有触发词),不参与路由判定。
55    #[serde(default, rename = "triggerDescription")]
56    pub trigger_description: Option<String>,
57    /// 支持的操作系统标识(如 `["windows"]`)
58    #[serde(rename = "supportedOs")]
59    pub supported_os: Vec<String>,
60    /// 默认搜索候选项优先级
61    #[serde(rename = "priority")]
62    pub priority: u32,
63    /// 项目主页 URL(可选)
64    #[serde(default, rename = "homepage")]
65    pub homepage: Option<String>,
66    /// 开源许可证标识(可选),如 `MIT`、`GPL-3.0`
67    #[serde(default, rename = "license")]
68    pub license: Option<String>,
69}
70
71/// 运行时配置段。
72#[derive(Debug, Clone, Default, Serialize, Deserialize)]
73pub struct RuntimeSection {
74    /// 可执行文件路径(相对于插件目录),如 `./bin/my-plugin`
75    #[serde(rename = "command")]
76    pub command: String,
77    /// 启动参数列表
78    #[serde(default, rename = "args")]
79    pub args: Vec<String>,
80    /// 启动超时秒数,默认 10 秒
81    #[serde(default = "default_startup_timeout", rename = "startupTimeout")]
82    pub startup_timeout: u64,
83    /// 崩溃后是否自动重启,默认 true
84    #[serde(default = "default_true", rename = "autoRestart")]
85    pub auto_restart: bool,
86    /// 最大重启次数,超过后不再自动拉起,默认 3
87    #[serde(default = "default_max_restart", rename = "maxRestart")]
88    pub max_restart: u32,
89}
90
91/// 组件声明段。
92/// 插件在此声明对外提供哪些能力。
93#[derive(Debug, Clone, Default, Serialize, Deserialize)]
94pub struct ComponentsSection {
95    /// 能力列表,可选值见 `REQUIRED_PROVIDES_VALUES`。
96    /// 插件可以声明多个能力(如同时提供 `data_source` 和 `action_executor`),
97    /// 每个能力在构建期对应一个 `RemoteConfigurableAdapter`。
98    #[serde(default = "default_provides", rename = "provides")]
99    pub provides: Vec<String>,
100}
101
102/// 前端 UI 入口段(可选)。
103/// 第三方插件可以注册自定义 Vue 面板,嵌入宿主设置页。
104#[derive(Debug, Clone, Serialize, Deserialize)]
105pub struct UiSection {
106    /// 插件信息面板入口组件路径
107    #[serde(rename = "panelEntry")]
108    pub panel_entry: Option<String>,
109    /// 插件配置面板入口组件路径
110    #[serde(rename = "settingsEntry")]
111    pub settings_entry: Option<String>,
112    /// 搜索结果项自定义渲染组件路径
113    #[serde(rename = "resultItemEntry")]
114    pub result_item_entry: Option<String>,
115}
116
117/// 图标配置段(可选)。
118#[derive(Debug, Clone, Serialize, Deserialize)]
119pub struct IconSection {
120    /// 图标文件路径(相对于插件目录),建议使用 PNG 或 SVG
121    #[serde(rename = "path")]
122    pub path: String,
123}
124
125fn default_startup_timeout() -> u64 {
126    10
127}
128fn default_true() -> bool {
129    true
130}
131fn default_max_restart() -> u32 {
132    3
133}
134fn default_provides() -> Vec<String> {
135    vec![]
136}
137
138/// 必须存在的 manifest 字段。
139pub const REQUIRED_PROVIDES_VALUES: &[&str] = &[
140    "plugin",
141    "data_source",
142    "action_executor",
143    "search_engine",
144    "score_booster",
145    "keyword_optimizer",
146    "keyword_injector",
147];
148
149/// 反向域名格式插件 ID 的正则表达式。
150pub const PLUGIN_ID_RE: &str = r"\A[a-z][a-z0-9]*(\.[a-z][a-z0-9_-]*)+\z";