Skip to main content

zerolaunch_plugin_protocol/
messages.rs

1use serde::{Deserialize, Serialize};
2use zerolaunch_plugin_api::config::ComponentType;
3use zerolaunch_plugin_api::host::PluginSdkConfig;
4use zerolaunch_plugin_api::services::focus_monitor::FocusEvent;
5use zerolaunch_plugin_api::services::hotkey::types::{HotkeyEvent, HotkeyEventFilter};
6use zerolaunch_plugin_api::services::installation_monitor::types::InstallationEvent;
7use zerolaunch_plugin_api::services::shell::CommandRunMode;
8use zerolaunch_plugin_api::services::IconRequest;
9use zerolaunch_plugin_api::{
10    CandidateCacheSnapshot, CandidateId, ExecutionContext, KeywordInputSource, PluginContext,
11    Query, ScoredCandidate, SearchCandidate, TargetType,
12};
13
14// ─── plugin/initialize ───────────────────────────────────────────
15
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct InitializeParams {
18    #[serde(rename = "hostVersion")]
19    pub host_version: String,
20    #[serde(rename = "protocolVersion")]
21    pub protocol_version: String,
22    #[serde(rename = "dataDir")]
23    pub data_dir: String,
24    #[serde(rename = "logDir")]
25    pub log_dir: String,
26    #[serde(rename = "pluginId")]
27    pub plugin_id: String,
28    #[serde(rename = "locale")]
29    pub locale: String,
30}
31
32#[derive(Debug, Clone, Serialize, Deserialize)]
33pub struct InitializeResult {
34    #[serde(rename = "protocolVersion")]
35    pub protocol_version: String,
36}
37
38// ─── plugin/get_components ───────────────────────────────────────
39
40#[derive(Debug, Clone, Serialize, Deserialize)]
41pub struct ComponentDescriptor {
42    #[serde(rename = "componentId")]
43    pub component_id: String,
44    #[serde(rename = "componentName")]
45    pub component_name: String,
46    #[serde(rename = "componentDescription", default)]
47    pub component_description: String,
48    #[serde(rename = "componentType")]
49    pub component_type: ComponentType,
50    #[serde(rename = "kind")]
51    pub kind: ComponentKind,
52    #[serde(rename = "priority", default = "default_component_priority")]
53    pub priority: u32,
54}
55
56/// 默认组件优先级,与 `Configurable::priority()` 的默认值(50)一致。
57fn default_component_priority() -> u32 {
58    50
59}
60
61/// 与内置插件完全对等:Plugin / DataSource / ActionExecutor / SearchEngine /
62/// ScoreBooster / KeywordOptimizer / KeywordInjector 均可由第三方插件提供,
63/// 宿主按 kind 注册进对应管道(触发词路由 / 候选采集 / 执行器 / 搜索管道 / 候选管道)。
64#[derive(Debug, Clone, Serialize, Deserialize)]
65#[serde(tag = "type")]
66pub enum ComponentKind {
67    /// 主插件组件(插件级元数据由宿主从清单读取)。
68    #[serde(rename = "plugin")]
69    Plugin,
70    #[serde(rename = "data_source")]
71    DataSource,
72    #[serde(rename = "action_executor")]
73    ActionExecutor {
74        #[serde(rename = "targetTypes")]
75        target_types: Vec<TargetType>,
76    },
77    /// 搜索引擎 —— 参与搜索管道(与内置引擎互斥,仅允许一个启用)。
78    #[serde(rename = "search_engine")]
79    SearchEngine,
80    /// 分数增强器 —— 在引擎打分后追加分数修正(多个可同时启用)。
81    #[serde(rename = "score_booster")]
82    ScoreBooster,
83    /// 关键词优化器 —— 在候选管道中扩展搜索关键词。
84    /// input_source / priority 为声明属性,经 keyword_optimizer_info RPC 拉取。
85    #[serde(rename = "keyword_optimizer")]
86    KeywordOptimizer,
87    /// 关键词注入器 —— 基于候选项完整上下文注入额外关键词。
88    #[serde(rename = "keyword_injector")]
89    KeywordInjector,
90}
91
92// ─── plugin/get_settings_schema ──────────────────────────────────
93
94#[derive(Debug, Clone, Serialize, Deserialize)]
95pub struct GetSettingsSchemaParams {
96    #[serde(rename = "componentId")]
97    pub component_id: String,
98}
99
100// ─── plugin/get_settings ─────────────────────────────────────────
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
103pub struct GetSettingsParams {
104    #[serde(rename = "componentId")]
105    pub component_id: String,
106}
107
108// ─── plugin/apply_settings ───────────────────────────────────────
109
110#[derive(Debug, Clone, Serialize, Deserialize)]
111pub struct ApplySettingsParams {
112    #[serde(rename = "componentId")]
113    pub component_id: String,
114    #[serde(rename = "settings")]
115    pub settings: serde_json::Value,
116}
117
118// ─── plugin/validate_settings ────────────────────────────────────
119
120#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct ValidateSettingsParams {
122    #[serde(rename = "componentId")]
123    pub component_id: String,
124    #[serde(rename = "settings")]
125    pub settings: serde_json::Value,
126}
127
128#[derive(Debug, Clone, Serialize, Deserialize)]
129pub struct ValidateSettingsResult {
130    #[serde(default)]
131    pub error: Option<String>,
132}
133
134// ─── plugin/config_actions ───────────────────────────────────────
135//
136// 响应为裸数组 `Vec<ConfigActionDef>`(宿主 discover 流程以数组反序列化,
137// 与 get_settings_schema 的裸数组约定一致)。
138
139#[derive(Debug, Clone, Serialize, Deserialize)]
140pub struct ConfigActionsParams {
141    #[serde(rename = "componentId")]
142    pub component_id: String,
143}
144
145// ─── plugin/execute_config_action ────────────────────────────────
146
147#[derive(Debug, Clone, Serialize, Deserialize)]
148pub struct ExecuteConfigActionParams {
149    #[serde(rename = "componentId")]
150    pub component_id: String,
151    #[serde(rename = "action")]
152    pub action: String,
153    #[serde(rename = "params")]
154    pub params: serde_json::Value,
155}
156
157// ─── plugin/query ────────────────────────────────────────────────
158
159#[derive(Debug, Clone, Serialize, Deserialize)]
160pub struct QueryParams {
161    #[serde(rename = "pluginId")]
162    pub plugin_id: String,
163    #[serde(rename = "ctx")]
164    pub ctx: PluginContext,
165    #[serde(rename = "query")]
166    pub query: Query,
167}
168
169// ─── plugin/match_query ──────────────────────────────────────────
170
171/// `plugin/match_query` 请求参数 —— 宿主路由阶段询问插件是否接管当前输入。
172///
173/// 使用范围:宿主(`RemoteComponent` → SDK 分发);对全部启用中的行内插件调用。
174/// 响应为布尔值(true = 接管)。
175#[derive(Debug, Clone, Serialize, Deserialize)]
176pub struct MatchQueryParams {
177    /// 用户在搜索栏中输入的原始字符串(未做小写化等预处理)。
178    #[serde(rename = "rawQuery")]
179    pub raw_query: String,
180    /// 该插件声明的触发词(宿主从清单/代码元数据读取后随请求下发)。
181    /// 用途:让插件的默认 `match_query` 实现能就地完成框架关键词判定,无需在插件代码里重复声明。
182    #[serde(rename = "triggerKeywords")]
183    pub trigger_keywords: Vec<String>,
184}
185
186// ─── plugin/execute_action ───────────────────────────────────────
187
188#[derive(Debug, Clone, Serialize, Deserialize)]
189pub struct ExecuteActionParams {
190    #[serde(rename = "pluginId")]
191    pub plugin_id: String,
192    #[serde(rename = "ctx")]
193    pub ctx: PluginContext,
194    #[serde(rename = "actionId")]
195    pub action_id: String,
196    #[serde(rename = "payload")]
197    pub payload: serde_json::Value,
198}
199
200// ─── plugin/fetch_candidates ─────────────────────────────────────
201
202#[derive(Debug, Clone, Serialize, Deserialize)]
203pub struct FetchCandidatesParams {
204    #[serde(rename = "componentId")]
205    pub component_id: String,
206}
207
208/// Serializable candidate payload returned by remote DataSource plugins.
209/// The host reconstructs CachedCandidateData from these on receipt.
210#[derive(Debug, Clone, Serialize, Deserialize)]
211pub struct FetchCandidatesResult {
212    #[serde(rename = "candidates")]
213    pub candidates: Vec<SearchCandidate>,
214}
215
216// ─── plugin/supported_target_types ───────────────────────────────
217
218#[derive(Debug, Clone, Serialize, Deserialize)]
219pub struct SupportedTargetTypesParams {
220    #[serde(rename = "componentId")]
221    pub component_id: String,
222}
223
224// ─── plugin/supported_actions ────────────────────────────────────
225
226#[derive(Debug, Clone, Serialize, Deserialize)]
227pub struct SupportedActionsParams {
228    #[serde(rename = "componentId")]
229    pub component_id: String,
230    #[serde(rename = "targetType")]
231    pub target_type: TargetType,
232}
233
234// ─── plugin/executor_execute ─────────────────────────────────────
235
236#[derive(Debug, Clone, Serialize, Deserialize)]
237pub struct ExecutorExecuteParams {
238    #[serde(rename = "componentId")]
239    pub component_id: String,
240    /// 完整执行上下文原样透传(与进程内 ActionExecutor 拿到的 ExecutionContext 一致:
241    /// target / display_name / user_args / parameter_snapshot / locale)。
242    #[serde(rename = "executionCtx")]
243    pub execution_ctx: ExecutionContext,
244    #[serde(rename = "actionId")]
245    pub action_id: String,
246}
247
248#[derive(Debug, Clone, Serialize, Deserialize)]
249pub struct ExecutorExecuteResult {
250    #[serde(default)]
251    pub error: Option<String>,
252}
253
254// ─── plugin/calculate_scores ─────────────────────────────────────
255//
256// SearchEngine 组件:对缓存候选计算分数(含全量候选与查询词,宿主按
257// ScoredCandidate 列表重建结果)。
258
259/// plugin/calculate_scores 请求参数。
260#[derive(Debug, Clone, Serialize, Deserialize)]
261pub struct CalculateScoresParams {
262    /// 目标组件 id(SearchEngine 组件)。
263    #[serde(rename = "componentId")]
264    pub component_id: String,
265    /// 全量候选快照(宿主 CachedCandidateData::to_data 导出,id 保真)。
266    #[serde(rename = "candidates")]
267    pub candidates: CandidateCacheSnapshot,
268    /// 用户查询词。
269    #[serde(rename = "query")]
270    pub query: String,
271}
272
273// ─── plugin/booster_boost ────────────────────────────────────────
274//
275// ScoreBooster 组件:对已计算分数做增强,返回增强后的分数列表(索引与传入一致)。
276
277/// plugin/booster_boost 请求参数。
278#[derive(Debug, Clone, Serialize, Deserialize)]
279pub struct BoosterBoostParams {
280    /// 目标组件 id(ScoreBooster 组件)。
281    #[serde(rename = "componentId")]
282    pub component_id: String,
283    /// 全量候选快照(宿主 CachedCandidateData::to_data 导出,id 保真)。
284    #[serde(rename = "candidates")]
285    pub candidates: CandidateCacheSnapshot,
286    /// 引擎计算出的当前分数列表。
287    #[serde(rename = "scored")]
288    pub scored: Vec<ScoredCandidate>,
289    /// 用户查询词。
290    #[serde(rename = "query")]
291    pub query: String,
292}
293
294// ─── plugin/booster_record ───────────────────────────────────────
295//
296// ScoreBooster 组件:记录用户确认(选中候选 → 学习用户习惯)。
297
298/// plugin/booster_record 请求参数。
299#[derive(Debug, Clone, Serialize, Deserialize)]
300pub struct BoosterRecordParams {
301    /// 目标组件 id(ScoreBooster 组件)。
302    #[serde(rename = "componentId")]
303    pub component_id: String,
304    /// 被选中候选项的 id(宿主侧缓存内的原始 id)。
305    #[serde(rename = "candidateId")]
306    pub candidate_id: CandidateId,
307    /// 全量候选快照(宿主 CachedCandidateData::to_data 导出,id 保真)。
308    #[serde(rename = "candidates")]
309    pub candidates: CandidateCacheSnapshot,
310    /// 用户查询词。
311    #[serde(rename = "query")]
312    pub query: String,
313}
314
315// ─── plugin/keyword_optimizer_info ───────────────────────────────
316//
317// KeywordOptimizer 组件的声明属性(input_source / priority),
318// 宿主在发现与设置变更时经本方法拉取并缓存。
319//
320// 响应为裸 `KeywordOptimizerInfo`。
321//
322// 载荷说明:`inputSource`(嵌套对象)取代了 1.x 的 `usesContext: bool`,属载荷级
323// breaking change,已随协议 major 提升到 2.0 —— 1.x 插件在 initialize 握手期被拒绝。
324
325/// KeywordOptimizer 组件的优化属性(经 keyword_optimizer_info RPC 拉取)。
326#[derive(Debug, Clone, Serialize, Deserialize)]
327pub struct KeywordOptimizerInfo {
328    /// 优化器消费的关键词产物来源(分层 DAG-lite 输入层)。
329    #[serde(rename = "inputSource")]
330    pub input_source: KeywordInputSource,
331    /// 链式执行优先级,小者先执行。
332    #[serde(rename = "priority")]
333    pub priority: u32,
334}
335
336/// plugin/keyword_optimizer_info 请求参数。
337#[derive(Debug, Clone, Serialize, Deserialize)]
338pub struct KeywordOptimizerInfoParams {
339    /// 目标组件 id(KeywordOptimizer 组件)。
340    #[serde(rename = "componentId")]
341    pub component_id: String,
342}
343
344// ─── plugin/keyword_optimize ─────────────────────────────────────
345//
346// KeywordOptimizer 组件:优化单个关键词(宿主按链序逐级调用)。
347//
348// 响应为裸 `Vec<String>`(优化生成的新关键词)。
349
350/// plugin/keyword_optimize 请求参数。
351#[derive(Debug, Clone, Serialize, Deserialize)]
352pub struct KeywordOptimizeParams {
353    /// 目标组件 id(KeywordOptimizer 组件)。
354    #[serde(rename = "componentId")]
355    pub component_id: String,
356    /// 待优化的关键词。
357    #[serde(rename = "keyword")]
358    pub keyword: String,
359    /// 本次调用携带的来源层(供第三方优化器决策,宿主按声明来源调用)。
360    /// serde default:字段缺失时反序列化回退 Refined,避免 INVALID_PARAMS
361    /// 导致优化器整体跳过。
362    #[serde(rename = "inputSource", default)]
363    pub input_source: KeywordInputSource,
364}
365
366// KeywordInjector 组件:对单个候选注入关键词(与内置逐候选语义一致)。
367//
368// 响应为裸 `Vec<String>`。
369
370/// plugin/keyword_inject 请求参数。
371#[derive(Debug, Clone, Serialize, Deserialize)]
372pub struct KeywordInjectParams {
373    /// 目标组件 id(KeywordInjector 组件)。
374    #[serde(rename = "componentId")]
375    pub component_id: String,
376    /// 待注入的候选项(完整上下文:target、keywords 等)。
377    #[serde(rename = "candidate")]
378    pub candidate: SearchCandidate,
379}
380
381// ─── plugin/init ─────────────────────────────────────────────────
382//
383// 插件初始化钩子:宿主在组件注册完成后调用,通知插件进程完成初始化。
384// 与 plugin/initialize(进程级握手)不同层:init 携带真实查询上下文
385// (trace_id / locale),对应内置插件启动期的 Plugin::init。
386
387/// plugin/init 请求参数。
388#[derive(Debug, Clone, Serialize, Deserialize)]
389pub struct InitParams {
390    /// 目标插件 id(宿主覆盖为 manifest 插件 id)。
391    #[serde(rename = "pluginId")]
392    pub plugin_id: String,
393    /// 宿主构造的初始化上下文(真实 trace_id 与当前语言)。
394    #[serde(rename = "ctx")]
395    pub ctx: PluginContext,
396}
397
398// ─── plugin/interaction_policy ───────────────────────────────────
399//
400// 响应为裸 `PanelInteraction`(与 get_settings_schema 的裸数组约定一致)。
401// 策略为插件级语义:宿主仅对 Plugin 种类组件调用;SDK 恒返回主插件策略。
402
403/// plugin/interaction_policy 请求参数。
404#[derive(Debug, Clone, Serialize, Deserialize)]
405pub struct InteractionPolicyParams {
406    /// 目标组件 id(仅 Plugin 种类组件会收到该请求)。
407    #[serde(rename = "componentId")]
408    pub component_id: String,
409}
410
411// ─── plugin/get_default_enabled ──────────────────────────────────
412//
413// 响应为裸 `bool`。
414
415/// plugin/get_default_enabled 请求参数。
416#[derive(Debug, Clone, Serialize, Deserialize)]
417pub struct GetDefaultEnabledParams {
418    /// 目标组件 id。
419    #[serde(rename = "componentId")]
420    pub component_id: String,
421}
422
423// ─── host/log ────────────────────────────────────────────────────
424
425#[derive(Debug, Clone, Serialize, Deserialize)]
426pub struct LogParams {
427    #[serde(rename = "level")]
428    pub level: String,
429    #[serde(rename = "message")]
430    pub message: String,
431}
432
433// ─── host/notify ─────────────────────────────────────────────────
434
435#[derive(Debug, Clone, Serialize, Deserialize)]
436pub struct NotifyParams {
437    #[serde(rename = "title")]
438    pub title: String,
439    #[serde(rename = "message")]
440    pub message: String,
441}
442
443// ─── host/shell.open ─────────────────────────────────────────────
444
445#[derive(Debug, Clone, Serialize, Deserialize)]
446pub struct ShellOpenParams {
447    #[serde(rename = "target")]
448    pub target: String,
449}
450
451// ─── host/shell.open_folder ─────────────────────────────────────
452
453#[derive(Debug, Clone, Serialize, Deserialize)]
454pub struct ShellOpenFolderParams {
455    #[serde(rename = "path")]
456    pub path: String,
457}
458
459// ─── host/shell.execute_elevation ────────────────────────────────
460
461#[derive(Debug, Clone, Serialize, Deserialize)]
462pub struct ShellExecuteElevationParams {
463    #[serde(rename = "path")]
464    pub path: String,
465}
466
467// ─── host/shell.execute_command ──────────────────────────────────
468
469/// `host/shell.execute_command` 参数 —— 由 SDK `HostProxy` 代理构造,
470/// 宿主 `host_handler` 反序列化后转发到 `PluginHandle::shell_execute_command`。
471#[derive(Debug, Clone, Serialize, Deserialize)]
472pub struct ShellExecuteCommandParams {
473    /// 要执行的命令字符串(原样交给 cmd 解析,不做参数转义)。
474    #[serde(rename = "cmd")]
475    pub cmd: String,
476    /// 执行方式;载荷缺省(旧插件只发 cmd)时按后台静默执行处理。
477    #[serde(rename = "mode", default)]
478    pub mode: CommandRunMode,
479}
480
481// ─── host/window.activate_by_process ─────────────────────────────
482
483#[derive(Debug, Clone, Serialize, Deserialize)]
484pub struct WindowActivateParams {
485    #[serde(rename = "pid")]
486    pub pid: u32,
487}
488
489// ─── host/icon.get / host/icon.extract / host/icon.refresh ───────
490// 返回值为图标字节的 base64 字符串。字节格式为 WebP(编码失败回退可能为
491// PNG),消费方按字节头嗅探 MIME(RIFF....WEBP → image/webp,否则 image/png)。
492// icon.get 在提取失败时回退默认图标;extract / refresh 失败返回错误。
493
494/// 图标请求参数(icon.get / extract / refresh 共用)。
495#[derive(Debug, Clone, Serialize, Deserialize)]
496pub struct IconRequestParams {
497    /// 图标提取请求(文件路径 / 网址 / 扩展名 / 已编码数据)。
498    #[serde(rename = "request")]
499    pub request: IconRequest,
500}
501
502// ─── host/path.resolve ───────────────────────────────────────────
503
504#[derive(Debug, Clone, Serialize, Deserialize)]
505pub struct PathResolveParams {
506    #[serde(rename = "kind")]
507    pub kind: String,
508}
509
510// ─── host/resource.upload ────────────────────────────────────────
511
512#[derive(Debug, Clone, Serialize, Deserialize)]
513pub struct ResourceUploadParams {
514    #[serde(rename = "resourceId")]
515    pub resource_id: String,
516    #[serde(rename = "filePath")]
517    pub file_path: String,
518    #[serde(rename = "maxSize")]
519    #[serde(default)]
520    pub max_size: Option<usize>,
521}
522
523// ─── host/resource.put ────────────────────────────────────────────
524
525#[derive(Debug, Clone, Serialize, Deserialize)]
526pub struct ResourcePutParams {
527    #[serde(rename = "resourceId")]
528    pub resource_id: String,
529    #[serde(rename = "bytesB64")]
530    pub bytes_b64: String,
531}
532
533// ─── host/resource.get ───────────────────────────────────────────
534
535#[derive(Debug, Clone, Serialize, Deserialize)]
536pub struct ResourceGetParams {
537    #[serde(rename = "resourceId")]
538    pub resource_id: String,
539}
540
541// ─── host/resource.delete ────────────────────────────────────────
542
543#[derive(Debug, Clone, Serialize, Deserialize)]
544pub struct ResourceDeleteParams {
545    #[serde(rename = "resourceId")]
546    pub resource_id: String,
547}
548
549// ─── host/resource.list ──────────────────────────────────────────
550
551#[derive(Debug, Clone, Serialize, Deserialize)]
552pub struct ResourceListParams {}
553
554// ─── host/parameter.resolve ──────────────────────────────────────
555
556#[derive(Debug, Clone, Serialize, Deserialize)]
557pub struct ParameterResolveParams {
558    #[serde(rename = "userArgs")]
559    pub user_args: Vec<String>,
560    /// 参数模板字符串(如 "https://google.com/search?q={query}")。
561    /// 命名注意:此字段是模板,不是插件 ID。字段曾名为 pluginId 但造成混淆,已更正。
562    #[serde(rename = "template")]
563    pub template: String,
564}
565
566// ─── host/sdk_config.update ──────────────────────────────────────
567
568/// 更新插件 SDK 配置的参数。
569///
570/// 由插件的 `host/sdk_config.update` 调用携带;宿主将该配置应用到
571/// 该插件的 PluginHandle(影响后续图标缓存等级等行为),立即生效。
572#[derive(Debug, Clone, Serialize, Deserialize)]
573pub struct SdkConfigUpdateParams {
574    /// 新的插件 SDK 配置;未设置字段表示沿用宿主当前值。
575    #[serde(rename = "config")]
576    pub config: PluginSdkConfig,
577}
578
579// ─── host/icon.override_cache ────────────────────────────────────
580
581/// 覆盖图标缓存条目为自定义图标文件的参数。
582#[derive(Debug, Clone, Serialize, Deserialize)]
583pub struct IconOverrideCacheParams {
584    /// 需要覆盖缓存图标的原始图标请求。
585    #[serde(rename = "request")]
586    pub request: IconRequest,
587    /// 用户选择的自定义图标文件路径。
588    #[serde(rename = "customIconPath")]
589    pub custom_icon_path: String,
590}
591
592// ─── host/window.activate_by_process ─────────────────────────────
593
594/// 按进程名激活窗口的参数。
595#[derive(Debug, Clone, Serialize, Deserialize)]
596pub struct WindowActivateByProcessParams {
597    /// 进程名(如 "chrome.exe")。
598    #[serde(rename = "processName")]
599    pub process_name: String,
600}
601
602// ─── host/window.activate_by_title ───────────────────────────────
603
604/// 按窗口标题片段激活窗口的参数。
605#[derive(Debug, Clone, Serialize, Deserialize)]
606pub struct WindowActivateByTitleParams {
607    /// 窗口标题片段。
608    #[serde(rename = "title")]
609    pub title: String,
610}
611
612// ─── host/clipboard.set_text ─────────────────────────────────────
613
614/// 写入系统剪贴板的参数。
615#[derive(Debug, Clone, Serialize, Deserialize)]
616pub struct ClipboardSetTextParams {
617    /// 待写入剪贴板的文本。
618    #[serde(rename = "text")]
619    pub text: String,
620}
621
622// ─── host/app.launch ─────────────────────────────────────────────
623// 返回值为启动进程的 PID。
624
625/// 启动已安装应用的参数。
626#[derive(Debug, Clone, Serialize, Deserialize)]
627pub struct AppLaunchParams {
628    /// 应用 ID(AppInfo.id / AppsFolder 条目 ID)。
629    #[serde(rename = "appId")]
630    pub app_id: String,
631    /// 启动参数列表;None 表示不传参数。
632    #[serde(rename = "args")]
633    #[serde(default)]
634    pub args: Option<Vec<String>>,
635}
636
637// ─── host/app.icon_path ──────────────────────────────────────────
638
639/// 查询内置应用图标资源路径的参数。
640#[derive(Debug, Clone, Serialize, Deserialize)]
641pub struct AppIconPathParams {
642    /// 资源名称(如 "tray_icon"、"terminal")。
643    #[serde(rename = "name")]
644    pub name: String,
645}
646
647// ─── host/path.resolve_lnk ───────────────────────────────────────
648
649/// 解析 .lnk 快捷方式目标的参数。
650#[derive(Debug, Clone, Serialize, Deserialize)]
651pub struct PathResolveLnkParams {
652    /// .lnk 文件路径。
653    #[serde(rename = "lnkPath")]
654    pub lnk_path: String,
655}
656
657// ─── host/path.localized_names ───────────────────────────────────
658
659/// 解析目录本地化文件名的参数。
660#[derive(Debug, Clone, Serialize, Deserialize)]
661pub struct PathLocalizedNamesParams {
662    /// 目标目录路径。
663    #[serde(rename = "dirPath")]
664    pub dir_path: String,
665}
666
667// ─── host/parameter.count_user / host/parameter.has_system ───────
668
669/// 参数模板查询参数(统计用户参数 / 判断系统参数共用)。
670#[derive(Debug, Clone, Serialize, Deserialize)]
671pub struct ParameterTemplateParams {
672    /// 参数模板字符串(如 "https://example.com?q={query}")。
673    #[serde(rename = "template")]
674    pub template: String,
675}
676
677// ─── host/cache.put ──────────────────────────────────────────────
678
679/// 写入插件本地缓存的参数。
680#[derive(Debug, Clone, Serialize, Deserialize)]
681pub struct CachePutParams {
682    /// 缓存域(插件内逻辑分组,需为非空且不含路径分隔符/..)。
683    #[serde(rename = "domain")]
684    pub domain: String,
685    /// 缓存键(域内唯一,允许子路径但不得逃逸域目录)。
686    #[serde(rename = "key")]
687    pub key: String,
688    /// 缓存字节数据的 base64 编码。
689    #[serde(rename = "bytesB64")]
690    pub bytes_b64: String,
691}
692
693// ─── host/cache.get ──────────────────────────────────────────────
694
695/// 读取插件本地缓存的参数。
696#[derive(Debug, Clone, Serialize, Deserialize)]
697pub struct CacheGetParams {
698    /// 缓存域。
699    #[serde(rename = "domain")]
700    pub domain: String,
701    /// 缓存键。
702    #[serde(rename = "key")]
703    pub key: String,
704}
705
706// ─── host/cache.delete ───────────────────────────────────────────
707
708/// 删除插件本地缓存条目的参数。
709#[derive(Debug, Clone, Serialize, Deserialize)]
710pub struct CacheDeleteParams {
711    /// 缓存域。
712    #[serde(rename = "domain")]
713    pub domain: String,
714    /// 缓存键。
715    #[serde(rename = "key")]
716    pub key: String,
717}
718
719// ─── host/cache.cleanup ──────────────────────────────────────────
720
721/// 按条目数上限清理插件本地缓存域的参数。
722#[derive(Debug, Clone, Serialize, Deserialize)]
723pub struct CacheCleanupParams {
724    /// 缓存域。
725    #[serde(rename = "domain")]
726    pub domain: String,
727    /// 保留的最大条目数,超出部分按修改时间从旧到新删除。
728    #[serde(rename = "maxEntries")]
729    pub max_entries: usize,
730}
731
732// ─── host/timer.set_timeout ──────────────────────────────────────
733// 返回值为宿主分配的定时器 ID(u64),到期由宿主推送 plugin/timer.fired。
734
735/// 创建一次性定时器的参数。
736#[derive(Debug, Clone, Serialize, Deserialize)]
737pub struct TimerSetTimeoutParams {
738    /// 延迟毫秒数。
739    #[serde(rename = "delayMs")]
740    pub delay_ms: u64,
741}
742
743// ─── host/timer.set_interval ─────────────────────────────────────
744
745/// 创建重复定时器的参数。
746#[derive(Debug, Clone, Serialize, Deserialize)]
747pub struct TimerSetIntervalParams {
748    /// 触发间隔毫秒数。
749    #[serde(rename = "intervalMs")]
750    pub interval_ms: u64,
751}
752
753// ─── host/timer.cancel ───────────────────────────────────────────
754
755/// 取消指定定时器的参数。
756#[derive(Debug, Clone, Serialize, Deserialize)]
757pub struct TimerCancelParams {
758    /// 定时器 ID(host/timer.set_* 的返回值)。
759    #[serde(rename = "id")]
760    pub id: u64,
761}
762
763// ─── host/timer.cancel_all ───────────────────────────────────────
764
765/// 取消本插件全部定时器的参数(无字段)。
766#[derive(Debug, Clone, Serialize, Deserialize)]
767pub struct TimerCancelAllParams {}
768
769// ─── plugin/timer.fired ──────────────────────────────────────────
770
771/// 宿主推送的定时器到期通知载荷。
772#[derive(Debug, Clone, Serialize, Deserialize)]
773pub struct TimerFiredParams {
774    /// 到期的定时器 ID。
775    #[serde(rename = "id")]
776    pub id: u64,
777}
778
779// ─── host/hotkey.subscribe ───────────────────────────────────────
780
781/// 订阅按键事件的参数。
782#[derive(Debug, Clone, Serialize, Deserialize)]
783pub struct HotkeySubscribeParams {
784    /// 插件内订阅 ID(宿主按 "{plugin_id}:{id}" 前缀化,退订时用同一 ID)。
785    #[serde(rename = "id")]
786    pub id: String,
787    /// 关注的事件过滤器(全部 / 指定快捷键 / 双击 Ctrl)。
788    #[serde(rename = "filter")]
789    pub filter: HotkeyEventFilter,
790}
791
792// ─── host/hotkey.unsubscribe ─────────────────────────────────────
793
794/// 退订按键事件的参数。
795#[derive(Debug, Clone, Serialize, Deserialize)]
796pub struct HotkeyUnsubscribeParams {
797    /// 订阅时使用的插件内 ID。
798    #[serde(rename = "id")]
799    pub id: String,
800}
801
802// ─── host/installation.subscribe / unsubscribe ───────────────────
803
804/// 订阅安装监控事件的参数。
805#[derive(Debug, Clone, Serialize, Deserialize)]
806pub struct InstallationSubscribeParams {
807    /// 插件内订阅 ID。
808    #[serde(rename = "id")]
809    pub id: String,
810}
811
812/// 退订安装监控事件的参数。
813#[derive(Debug, Clone, Serialize, Deserialize)]
814pub struct InstallationUnsubscribeParams {
815    /// 订阅时使用的插件内 ID。
816    #[serde(rename = "id")]
817    pub id: String,
818}
819
820// ─── host/focus.subscribe / unsubscribe ──────────────────────────
821
822/// 订阅窗口焦点事件的参数。
823#[derive(Debug, Clone, Serialize, Deserialize)]
824pub struct FocusSubscribeParams {
825    /// 插件内订阅 ID。
826    #[serde(rename = "id")]
827    pub id: String,
828}
829
830/// 退订窗口焦点事件的参数。
831#[derive(Debug, Clone, Serialize, Deserialize)]
832pub struct FocusUnsubscribeParams {
833    /// 订阅时使用的插件内 ID。
834    #[serde(rename = "id")]
835    pub id: String,
836}
837
838// ─── plugin/hotkey.event / plugin/installation.event / plugin/focus.event ──
839// 载荷携带订阅时的插件内 ID,使插件可把事件路由到对应订阅的处理函数。
840
841/// 宿主推送的按键事件载荷。
842#[derive(Debug, Clone, Serialize, Deserialize)]
843pub struct HotkeyEventParams {
844    /// 订阅时使用的插件内 ID。
845    #[serde(rename = "id")]
846    pub id: String,
847    /// 事件内容(全局快捷键 / 双击 Ctrl)。
848    #[serde(rename = "event")]
849    pub event: HotkeyEvent,
850}
851
852/// 宿主推送的安装监控事件载荷。
853#[derive(Debug, Clone, Serialize, Deserialize)]
854pub struct InstallationEventParams {
855    /// 订阅时使用的插件内 ID。
856    #[serde(rename = "id")]
857    pub id: String,
858    /// 事件内容(变化类型 + 变化路径)。
859    #[serde(rename = "event")]
860    pub event: InstallationEvent,
861}
862
863/// 宿主推送的窗口焦点事件载荷。
864#[derive(Debug, Clone, Serialize, Deserialize)]
865pub struct FocusEventParams {
866    /// 订阅时使用的插件内 ID。
867    #[serde(rename = "id")]
868    pub id: String,
869    /// 事件内容(当前仅失去焦点)。
870    #[serde(rename = "event")]
871    pub event: FocusEvent,
872}