@linkdesk/contracts 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +35 -0
- package/linkdesk.d.ts +1941 -0
- package/package.json +24 -0
package/linkdesk.d.ts
ADDED
|
@@ -0,0 +1,1941 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🔥 linkdesk.d.ts——window.linkdesk 插件 API 契约(自动生成,勿手改)
|
|
3
|
+
*
|
|
4
|
+
* 生成源:src/core/api/linkdesk-api.ts + linkdesk-api/(13 域接口 + types.ts)
|
|
5
|
+
* + src/core/types/ipc/* + src/core/types/pool/*(wire 载荷类型)
|
|
6
|
+
* 生成器:scripts/generate-contract.mjs(Route C——契约类型文件为源,纯类型打包)
|
|
7
|
+
* 改契约源 → 跑 `node scripts/generate-contract.mjs`(npm run check 里 check-contracts 强制)
|
|
8
|
+
*
|
|
9
|
+
* 用法(第三方插件作者):
|
|
10
|
+
* 拷贝本文件进项目 + tsconfig 引用,或 `npm i -D @linkdesk/contracts`(#22.6)
|
|
11
|
+
* import type { PluginListEntry } from "linkdesk";
|
|
12
|
+
* window.linkdesk.filesystem.readFile(...) // ambient 类型直出
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
// ── 契约类型 ──
|
|
16
|
+
export interface LinkDeskCommand {
|
|
17
|
+
id: string;
|
|
18
|
+
title: string;
|
|
19
|
+
category?: string;
|
|
20
|
+
}
|
|
21
|
+
/** 配方贡献域——theme 元数据 domains(混搭来源过滤)+ theme:changed 载荷(域级细粒度刷新)共用(06 §2/§6.2)。
|
|
22
|
+
* 五域:colors(配色,colorways 恒贡献) + appearance 四风格域(radius/glass/font/background)。
|
|
23
|
+
* E5.8#132:surface 域删——per-surface 精调死键(A 删拍板),玻璃表面形态 token(--surface-*)归 glass 域。 */
|
|
24
|
+
export type ThemeDomain = "colors" | "font" | "radius" | "glass" | "background";
|
|
25
|
+
/** 配置 schema 中的单个属性定义——E5.8#41.14 🛤 补全 uiHint/minimum/maximum/renderHint/dependsOn
|
|
26
|
+
* (壳 SettingsView renderControl/SettingRow 官方控件切换 + 依赖显隐字段,与 SettingsView/types ConfigProperty 对齐) */
|
|
27
|
+
export interface LinkDeskConfigProperty {
|
|
28
|
+
type: string;
|
|
29
|
+
default?: unknown;
|
|
30
|
+
description?: string;
|
|
31
|
+
enum?: string[];
|
|
32
|
+
enumDescriptions?: string[];
|
|
33
|
+
/** 控件提示——uiHint 优先:plugin.json 声明式控件选择(renderControl 读它切 combobox/textarea/color 等) */
|
|
34
|
+
uiHint?: string;
|
|
35
|
+
/** 数值下限——uiHint 数值控件 min 校验 */
|
|
36
|
+
minimum?: number;
|
|
37
|
+
/** 数值上限——uiHint 数值控件 max 校验 */
|
|
38
|
+
maximum?: number;
|
|
39
|
+
/** 渲染提示——renderControl 第二判据("action" 渲染操作按钮 / "color" 渲染色块预览) */
|
|
40
|
+
renderHint?: string;
|
|
41
|
+
/** 等宽限定——仅 uiHint "fontFamily" 有意义。true/缺省 = 只列等宽族(编辑器字体);false = 全字族(UI 字体)。E5.8#50.20 */
|
|
42
|
+
monoOnly?: boolean;
|
|
43
|
+
/** 依赖条件——本项仅在 dependsOn.key 配置值 === value 时显示(SettingRow 读它显隐整行) */
|
|
44
|
+
dependsOn?: {
|
|
45
|
+
key: string;
|
|
46
|
+
value: unknown;
|
|
47
|
+
};
|
|
48
|
+
/** 动态下拉数据源——uiHint "select" 时读取(渲染时调 theme.listRecipes() 动态取,E5.8#50.23)。
|
|
49
|
+
* "theme.colorways" = 活动配方(app.theme)配色变体(选项带预览色块);
|
|
50
|
+
* "theme.sources" = 混搭来源(按 optionsFromDomain 过滤 RecipeMeta.domains)。 */
|
|
51
|
+
optionsFrom?: string;
|
|
52
|
+
/** 混搭来源域过滤——optionsFrom "theme.sources" 时按此域过滤 RecipeMeta.domains(10 §2 六域) */
|
|
53
|
+
optionsFromDomain?: ThemeDomain;
|
|
54
|
+
/** E5.8#50.26:renderHint "action" 按钮动作——点击执行此壳命令(第三方设置 UI 经 commands.executeCommand 触发) */
|
|
55
|
+
actionCommand?: string;
|
|
56
|
+
/** E5.8#50.26:renderHint "action" 按钮禁用条件——全部 {key,value} 匹配当前配置值时禁用 */
|
|
57
|
+
actionDisabledAll?: Array<{
|
|
58
|
+
key: string;
|
|
59
|
+
value: unknown;
|
|
60
|
+
}>;
|
|
61
|
+
/** E5.8#78:组内二级标题——SettingsView 把同 group 的 key 归到子标题下渲染;无 group 保持平铺(零侵入) */
|
|
62
|
+
group?: string;
|
|
63
|
+
/** E5.8#77:数值单位——uiHint "slider" 值标签单位("×" / "px";空 = 裸数值) */
|
|
64
|
+
unit?: string;
|
|
65
|
+
}
|
|
66
|
+
/** 配置 schema——key → 属性定义(index signature 保持现有消费方) */
|
|
67
|
+
export interface LinkDeskConfigSchema {
|
|
68
|
+
[key: string]: LinkDeskConfigProperty;
|
|
69
|
+
}
|
|
70
|
+
/** 配置贡献条目——configuration.getConfigurationContributions() 返回形状(E5.8#41.14 🛤 命名)。
|
|
71
|
+
* 与壳 ConfigurationRegistry 组装的 [pluginId, { title, properties }] 对齐——第三方设置 UI 不再 need cast */
|
|
72
|
+
export type LinkDeskConfigurationContribution = [
|
|
73
|
+
string,
|
|
74
|
+
{
|
|
75
|
+
title: string;
|
|
76
|
+
properties: Record<string, unknown>;
|
|
77
|
+
}
|
|
78
|
+
];
|
|
79
|
+
/** 命令 + 配置命名空间面——对标 VS Code vscode.commands + workspace.getConfiguration */
|
|
80
|
+
export interface CommandsAPI {
|
|
81
|
+
/** 命令——对标 VS Code vscode.commands */
|
|
82
|
+
commands: {
|
|
83
|
+
/** @deprecated E3j #75——向后兼容别名,新代码用 executeCommand */
|
|
84
|
+
execute<T = void>(commandId: string, ...args: any[]): Promise<T>;
|
|
85
|
+
/** 执行壳侧命令 */
|
|
86
|
+
executeCommand<T = void>(commandId: string, ...args: any[]): Promise<T>;
|
|
87
|
+
/**
|
|
88
|
+
* 注册池内命令——handler 只存在于池渲染进程(视图 mount 时注册)。
|
|
89
|
+
* meta 同步到壳注册表:title 显示名(命令面板/右键菜单,重注册即动态更新——
|
|
90
|
+
* toggle 命令标题随状态翻转)、category 命令面板分组、when context key 过滤
|
|
91
|
+
* (传 "false" = 纯程序化命令,不进命令面板,仅供插件 API 调用)。
|
|
92
|
+
* plugin.json contributes.commands 未声明的命令经 meta 注册后同样可见/可执行。
|
|
93
|
+
* 真相源分工:壳 CommandRegistry = 显示真相源(title/category/when 唯一权威),
|
|
94
|
+
* 池 = 执行真相源(handler 唯一权威,永不跨进程)——meta 只同步显示面。
|
|
95
|
+
*/
|
|
96
|
+
registerCommand(commandId: string,
|
|
97
|
+
handler: (...args: any[]) => Promise<unknown> | unknown, meta?: {
|
|
98
|
+
title?: string;
|
|
99
|
+
category?: string;
|
|
100
|
+
when?: string;
|
|
101
|
+
}): void;
|
|
102
|
+
/** 注销插件的池内命令(约定:命令 ID 格式为 "pluginId.commandName")——随视图 unmount 调用 */
|
|
103
|
+
unregisterCommands(pluginId: string): void;
|
|
104
|
+
/** 获取所有已注册命令列表 */
|
|
105
|
+
getCommands(): Promise<LinkDeskCommand[]>;
|
|
106
|
+
/** 壳侧插件入口模块级注册(双进程执行壳侧半程)——壳 preload 独有 */
|
|
107
|
+
_executeShellLocal?(id: string, ...args: unknown[]): Promise<unknown>;
|
|
108
|
+
};
|
|
109
|
+
/** 配置—新名——对标 VS Code vscode.workspace.getConfiguration */
|
|
110
|
+
configuration: {
|
|
111
|
+
/** 读取配置值——运行时动态值,无类型参数默认 unknown;调用方显式 get<number>("k") 窄化或自行收窄 */
|
|
112
|
+
get<T = unknown>(key: string): Promise<T>;
|
|
113
|
+
/** 写入配置值 */
|
|
114
|
+
set(key: string, value: unknown): Promise<void>;
|
|
115
|
+
/** 获取配置 schema */
|
|
116
|
+
getSchema(key?: string): Promise<LinkDeskConfigSchema>;
|
|
117
|
+
/** 订阅配置变更——返回 unsubscribe 函数。值运行时动态,T 由订阅方 cb 推断(events.on 同款泛型,防逆变报错) */
|
|
118
|
+
onChange<T = unknown>(key: string, cb: (value: T) => void): () => void;
|
|
119
|
+
// ══ E5.7#76:以下 9 个方法为设置页专用(SettingsView 渲染/实时刷新/跳转)。
|
|
120
|
+
// 池 preload 注入(SettingsView 在池渲染)——required,壳 preload 无此面。
|
|
121
|
+
// 通用插件请用上面的 get/set/getSchema/onChange。 ══
|
|
122
|
+
getConfigurationContributions(): Promise<LinkDeskConfigurationContribution[]>;
|
|
123
|
+
inspectConfiguration(key: string): Promise<unknown>;
|
|
124
|
+
getUserSettings(): Promise<Record<string, unknown>>;
|
|
125
|
+
onDidChangeConfiguration(cb: (key: string, value: unknown) => void): () => void;
|
|
126
|
+
onPluginLifecycleChange(cb: () => void): () => void;
|
|
127
|
+
consumeSettingsGroup(): Promise<string | null>;
|
|
128
|
+
onRequestSettingsGroup(cb: (pluginId: string) => void): () => void;
|
|
129
|
+
consumeScrollToSetting(): Promise<string | null>;
|
|
130
|
+
onRequestScrollToSetting(cb: (key: string) => void): () => void;
|
|
131
|
+
/** E5.8#41.14 🔴 修复:切快捷键 tab——M1 同款双通道(替代错配 window 事件死路由)。
|
|
132
|
+
* mount 时消费 pending(未打开时"打开快捷键设置"命令的请求);无请求返回 null */
|
|
133
|
+
consumeOpenKeybindings(): Promise<{
|
|
134
|
+
query?: string;
|
|
135
|
+
} | null>;
|
|
136
|
+
/** E5.8#41.14:实时订阅——设置已打开时"打开快捷键设置"命令即时切 tab */
|
|
137
|
+
onRequestOpenKeybindings(cb: (payload: {
|
|
138
|
+
query?: string;
|
|
139
|
+
}) => void): () => void;
|
|
140
|
+
};
|
|
141
|
+
/** @deprecated E3j #75——向后兼容别名,新代码用 configuration */
|
|
142
|
+
config: CommandsAPI["configuration"];
|
|
143
|
+
}
|
|
144
|
+
/** E5.8#50.6:玻璃 + 悬浮面板质感字段——主题 JSON `surface`(缺省 = 无玻璃无悬浮)。
|
|
145
|
+
* 纹理 texture 与 glass 正交(⑬ 纸纹分区不带玻璃也能用 per-surface 纹理)。 */
|
|
146
|
+
export interface ThemeSurface {
|
|
147
|
+
/** 玻璃配方——缺省 = 无玻璃 */
|
|
148
|
+
type?: "glass";
|
|
149
|
+
/** backdrop blur px——0 = 关 */
|
|
150
|
+
blur?: number;
|
|
151
|
+
/** 饱和度增强——1 = 关 */
|
|
152
|
+
saturate?: number;
|
|
153
|
+
/** 玻璃面叠加色 */
|
|
154
|
+
tint?: string;
|
|
155
|
+
/** 玻璃面不透明度(合成层基线)——1 = 不透明 / 0 = 全透见背景。写 --glass-opacity token(tint 盖片
|
|
156
|
+
* opacity 消费)+ 播种反推进合成 alpha(#112:配方面基线,用户 app.glassOpacity 覆盖时优先) */
|
|
157
|
+
opacity?: number;
|
|
158
|
+
/** 液态玻璃顶部高光强度——0 = 关 */
|
|
159
|
+
specular?: number;
|
|
160
|
+
/** E5.8#63:顶部高光基色(发丝光边颜色)——缺省 = 白;alpha 仍走 specular */
|
|
161
|
+
specularColor?: string;
|
|
162
|
+
/** 形变过渡 ms——0 = 关 */
|
|
163
|
+
morph?: number;
|
|
164
|
+
/** 悬浮圆角 px——0 = 直角贴边 */
|
|
165
|
+
radius?: number;
|
|
166
|
+
/** 投影浮起——true = 悬浮投影(引擎映射 --shadow-lift) */
|
|
167
|
+
shadow?: boolean;
|
|
168
|
+
/** E5.8#50.28:可平铺纹理图资产路径(⑬ 纸纹分区)——应用全部 5 zone 表面,与 glass 正交独立生效 */
|
|
169
|
+
texture?: string;
|
|
170
|
+
/** 纹理不透明度——1 = 不透明 */
|
|
171
|
+
textureOpacity?: number;
|
|
172
|
+
}
|
|
173
|
+
/** E5.8#50.6:图片背景质感字段——主题 JSON `background`(缺省 = 无图) */
|
|
174
|
+
export interface ThemeBackground {
|
|
175
|
+
/** 图片路径——作者提供可解析 URL,引擎写入 `--bg-image` 时 url() 包裹 */
|
|
176
|
+
image?: string;
|
|
177
|
+
/** 图片层不透明度——1 = 不透明。引擎写 `--bg-opacity`(.background-layer 清晰底图)+ `--surface-bg-opacity`
|
|
178
|
+
* (镜像/纹理/切片 ::after 图像层);用户 app.backgroundOpacity 覆盖时双 token 齐写(#115:图与底统一淡出,避免底图淡而镜像恒显) */
|
|
179
|
+
opacity?: number;
|
|
180
|
+
/** 图片遮罩明暗(0-1 rgba 透明度)——0 = 无遮罩 */
|
|
181
|
+
mask?: number;
|
|
182
|
+
/** E5.8#63:遮罩基色(暗化层颜色)——缺省 = 黑;alpha 仍走 mask。仅 panorama 生效(同 mask) */
|
|
183
|
+
maskColor?: string;
|
|
184
|
+
/** E5.8#50.29:切片模式——"panorama"(默认)= 现全窗语义零变化;"zones" = 同图连续切片挂 5 zone 表面(⑭ 影像分区) */
|
|
185
|
+
mode?: "panorama" | "zones";
|
|
186
|
+
}
|
|
187
|
+
export interface LinkDeskTheme {
|
|
188
|
+
name: string;
|
|
189
|
+
type: "dark" | "light";
|
|
190
|
+
/** E5.8#50.6:玻璃/悬浮质感——主题 JSON `surface`(缺省 = 无玻璃无悬浮) */
|
|
191
|
+
surface?: ThemeSurface;
|
|
192
|
+
/** E5.8#50.6:图片背景——主题 JSON `background`(缺省 = 无图) */
|
|
193
|
+
background?: ThemeBackground;
|
|
194
|
+
pluginId?: string;
|
|
195
|
+
}
|
|
196
|
+
/** E5.8#50.18:配色变体元数据——theme.listRecipes() 返回(colorways[] 元素,06 §2)。
|
|
197
|
+
* 预览色供 ThemePicker 卡片取色;单配色配方 = 1 项。 */
|
|
198
|
+
export interface ColorwayMeta {
|
|
199
|
+
/** 配色变体 id——全局唯一(theme.setColorway 入参;app.themeColor 动态 enum 存此) */
|
|
200
|
+
id: string;
|
|
201
|
+
/** 配色显示名 */
|
|
202
|
+
name: string;
|
|
203
|
+
/** 预览色——强调色 + 窗口背景(卡片徽标取色用;缺省配色无该 token → 空串) */
|
|
204
|
+
preview: {
|
|
205
|
+
accent: string;
|
|
206
|
+
bgWindow: string;
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/** E5.8#50.18:配方元数据——theme.listRecipes() 返回(全部可用配方 + 配色变体 + 预览色,06 §2)。
|
|
210
|
+
* domains = 该配方贡献哪些域(混搭来源过滤依据,10 §2);type = 明暗类别。 */
|
|
211
|
+
export interface RecipeMeta {
|
|
212
|
+
id: string;
|
|
213
|
+
name: string;
|
|
214
|
+
type: "light" | "dark";
|
|
215
|
+
colorways: ColorwayMeta[];
|
|
216
|
+
domains: ThemeDomain[];
|
|
217
|
+
}
|
|
218
|
+
export interface LinkDeskLanguage {
|
|
219
|
+
id: string;
|
|
220
|
+
label: string;
|
|
221
|
+
pluginId: string;
|
|
222
|
+
}
|
|
223
|
+
/** 主题 + 语言 + 外观资产命名空间面——对标 VS Code 外观面 */
|
|
224
|
+
export interface AppearanceAPI {
|
|
225
|
+
theme: {
|
|
226
|
+
/** 获取当前主题 ID */
|
|
227
|
+
getCurrent(): Promise<string>;
|
|
228
|
+
/** 获取所有可用主题列表 */
|
|
229
|
+
getAvailable(): Promise<LinkDeskTheme[]>;
|
|
230
|
+
/** 应用主题 */
|
|
231
|
+
apply(themeId: string): Promise<void>;
|
|
232
|
+
// ── E5.8#50.18:配方/配色 06 §2 六方法——列表走 API(数据),选中走配置(持久化 app.*)──
|
|
233
|
+
/** 全部可用配方(含各配色变体 + 预览色)——ThemePicker 卡片 / 配色与混搭动态 SelectBox 数据源 */
|
|
234
|
+
listRecipes(): Promise<RecipeMeta[]>;
|
|
235
|
+
/** 当前活动配方/配色——合并配置计算(getActiveRecipe + app.theme/app.themeColor 回退) */
|
|
236
|
+
getActive(): Promise<{
|
|
237
|
+
recipeId: string;
|
|
238
|
+
colorwayId: string;
|
|
239
|
+
} | null>;
|
|
240
|
+
/** 当前生效 token 集(合并后)——appearanceMode→custom 播种、混搭预览 */
|
|
241
|
+
getEffectiveTokens(): Promise<Record<string, string>>;
|
|
242
|
+
/** 应用配方——落 app.theme(配色随配方自动跟随) */
|
|
243
|
+
setRecipe(recipeId: string): Promise<void>;
|
|
244
|
+
/** 应用配色变体——落 app.themeColor */
|
|
245
|
+
setColorway(colorwayId: string): Promise<void>;
|
|
246
|
+
/** 复位外观——对齐壳命令:app.appearanceMode→followTheme(onApply 级联清 9 覆盖 + 6 域来源 + 强调色回主题基线,E5.8#90 合并) */
|
|
247
|
+
resetAppearance(): Promise<void>;
|
|
248
|
+
/** 复位混搭——对齐壳命令:批复位 3 来源键回跟随主题(保持自定义模式,E5.8#90 app.mixMode 已删、#132 surface 域删) */
|
|
249
|
+
resetMix(): Promise<void>;
|
|
250
|
+
/** E5.8#88:外观覆盖键 → 主题/混搭基准种子值全集(设置页「已修改」徽标基准;无活动配方 → null) */
|
|
251
|
+
getBaselineSeeds(): Promise<Record<string, unknown> | null>;
|
|
252
|
+
};
|
|
253
|
+
language: {
|
|
254
|
+
/** 获取当前语言 ID */
|
|
255
|
+
getCurrent(): Promise<string>;
|
|
256
|
+
/** 获取所有可用语言列表 */
|
|
257
|
+
getAvailable(): Promise<LinkDeskLanguage[]>;
|
|
258
|
+
/** 切换语言 */
|
|
259
|
+
set(langId: string): Promise<void>;
|
|
260
|
+
/** 获取初始语言数据(WebView 加载时壳已推送) */
|
|
261
|
+
getInitial(): {
|
|
262
|
+
lang: string;
|
|
263
|
+
resources: Record<string, unknown>;
|
|
264
|
+
} | null;
|
|
265
|
+
/** 订阅语言变更——返回 unsubscribe */
|
|
266
|
+
onChange(cb: (data: {
|
|
267
|
+
lang: string;
|
|
268
|
+
resources: Record<string, unknown>;
|
|
269
|
+
}) => void): () => void;
|
|
270
|
+
};
|
|
271
|
+
/** E5.8#50.11:外观资产——本地选图拷贝入库(受控来源——用户任选路径不能 file:// 直读) */
|
|
272
|
+
appearance: {
|
|
273
|
+
/** 导入图片到 userData/appearance/(重名去重)——返回受控协议 URL(linkdesk-userdata://…,E5.8#64),
|
|
274
|
+
* 供 app.backgroundImage 持久化;沙箱经特权协议加载(plain 绝对路径被拦截) */
|
|
275
|
+
importImage(sourcePath: string): Promise<string>;
|
|
276
|
+
/** E5.8#153:打开外观存储目录(userData/appearance)——主进程解析路径并 shell.openPath 开资源管理器
|
|
277
|
+
* 内容(非高亮单文件);目录缺省也建(打开即见存储位置),openPath 失败抛错 fail-loud。 */
|
|
278
|
+
revealStorage(): Promise<void>;
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
/** 标签页命名空间面——对标 VS Code vscode.window.createTerminal() */
|
|
282
|
+
export interface TabsAPI {
|
|
283
|
+
tabs: {
|
|
284
|
+
create(type: string, opts?: Record<string, unknown>): Promise<unknown>;
|
|
285
|
+
openOrFocus(type: string, opts?: Record<string, unknown>): Promise<unknown>;
|
|
286
|
+
focus(tabId: string): Promise<void>;
|
|
287
|
+
close(tabId: string): Promise<void>;
|
|
288
|
+
focusBySourceId(sourceId: string): Promise<void>;
|
|
289
|
+
updateLabelBySourceId(sourceId: string, label: string): Promise<void>;
|
|
290
|
+
closeBySourceId(sourceId: string): Promise<void>;
|
|
291
|
+
/** E5.6#11.5g3:标签页激活订阅——文件树 autoReveal 消费(preload-pool 实有面,#98 补录契约) */
|
|
292
|
+
onDidChangeActiveTab(cb: (data: {
|
|
293
|
+
tabId: string;
|
|
294
|
+
pluginId?: string;
|
|
295
|
+
filePath?: string;
|
|
296
|
+
}) => void): () => void;
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* KeybindingRegistry 类型层——自 KeybindingRegistry.ts 拆出(E5.8#0d.10-8a)。
|
|
301
|
+
* 纯类型零逻辑。依赖方向:无(被 normalization / registry / chord / persistence / dispatch 消费)。
|
|
302
|
+
*/
|
|
303
|
+
export interface Keybinding {
|
|
304
|
+
/** 命令 ID */
|
|
305
|
+
command: string;
|
|
306
|
+
/** 快捷键字符串——如 "ctrl+k" / "ctrl+shift+b" */
|
|
307
|
+
key: string;
|
|
308
|
+
/** context key when 条件 */
|
|
309
|
+
when?: string;
|
|
310
|
+
/** 来源:user / plugin / builtin——同 key 时 user 优先 */
|
|
311
|
+
source: "user" | "plugin" | "builtin";
|
|
312
|
+
/** 插件 ID——卸载时精确匹配(B3 fix:原实现 source === "plugin" 会误删所有插件快捷键) */
|
|
313
|
+
pluginId?: string;
|
|
314
|
+
/** E3f #59-F:执行时透传给 executeCommand 的额外参数 */
|
|
315
|
+
args?: unknown[];
|
|
316
|
+
}
|
|
317
|
+
/** 壳→主进程快捷键表同步载荷(KeybindingRegistry.getKeybindingSyncData 输出) */
|
|
318
|
+
export interface KeybindingSyncData {
|
|
319
|
+
shortcuts: string[];
|
|
320
|
+
chordPrefixes: string[];
|
|
321
|
+
chordCombos: string[];
|
|
322
|
+
}
|
|
323
|
+
/** 键盘输入快照——主进程 before-input-event 归一化后转发的 executeShortcut 载荷 */
|
|
324
|
+
export interface KeyboardInput {
|
|
325
|
+
ctrlKey: boolean;
|
|
326
|
+
shiftKey: boolean;
|
|
327
|
+
altKey: boolean;
|
|
328
|
+
metaKey: boolean;
|
|
329
|
+
key: string;
|
|
330
|
+
code: string;
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* E5.8#46.8:主进程 before-input-event 转发的 executeShortcut 载荷——键盘快照 + 来源窗标注。
|
|
334
|
+
* KeyboardInput 保持纯净(纯键盘字段);来源作为组合类型必选字段(attachKeyboardRouting 恒有 windowId)。
|
|
335
|
+
* 壳 dispatch 据此按聚焦窗裁决快捷键(Ctrl+W 关本窗 tab)——与 ShellTabAction 顶层 sourceWindowId 同构(#46.4 归一化)。
|
|
336
|
+
*/
|
|
337
|
+
export interface ForwardedKeyboardInput extends KeyboardInput {
|
|
338
|
+
sourceWindowId: string;
|
|
339
|
+
}
|
|
340
|
+
/** 快捷键——壳/池双端注入(syncToMainProcess/onForwardedEvent 为壳侧独有)。池插件消费 setKeybindingCaptureActive(file-tree),必选 */
|
|
341
|
+
export interface KeybindingsAPI {
|
|
342
|
+
keybindings: {
|
|
343
|
+
getKeybindings(): Promise<Keybinding[]>;
|
|
344
|
+
getConflicts(): Promise<unknown>;
|
|
345
|
+
registerKeybinding(binding: unknown): Promise<void>;
|
|
346
|
+
saveUserKeybindings(): Promise<void>;
|
|
347
|
+
removeKeybindingForCommand(commandId: string): Promise<void>;
|
|
348
|
+
resetKeybindingToDefault(commandId: string): Promise<void>;
|
|
349
|
+
findKeybindingForCommand(commandId: string): Promise<Keybinding | undefined>;
|
|
350
|
+
setKeybindingCaptureActive(active: boolean): Promise<void>;
|
|
351
|
+
// 纯数据形参——contextBridge 结构化克隆丢 KeyboardEvent 原生属性(.key/.code 是 C++ getter),
|
|
352
|
+
// 调用方先提取字段再传(KeybindingSettingsView 同款)。真实 KeyboardEvent 天然满足此形状。
|
|
353
|
+
keyboardEventToKeyString(e: Pick<KeyboardEvent, "key" | "ctrlKey" | "shiftKey" | "altKey" | "metaKey">): string;
|
|
354
|
+
onChange(cb: () => void): () => void;
|
|
355
|
+
/** 壳→主进程同步快捷键表(chord 状态机查表) */
|
|
356
|
+
syncToMainProcess?(data: KeybindingSyncData): Promise<void>;
|
|
357
|
+
/** 接收主进程 before-input-event 转发的拦截事件(E5.8#46.8:载荷含 sourceWindowId——按聚焦窗裁决) */
|
|
358
|
+
onForwardedEvent?(cb: (input: ForwardedKeyboardInput) => void): () => void;
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
/** 进度通知句柄——progress=true 时 show() 返回 */
|
|
362
|
+
export interface NotificationHandle {
|
|
363
|
+
/** 更新进度消息 */
|
|
364
|
+
update(message: string): Promise<void>;
|
|
365
|
+
/** 完成——关闭进度通知,可选弹完成 toast */
|
|
366
|
+
finish(message?: string): Promise<void>;
|
|
367
|
+
/** 取消——直接关闭,不弹完成 toast */
|
|
368
|
+
cancel(): Promise<void>;
|
|
369
|
+
}
|
|
370
|
+
/** 插件在 plugin.json 里声明的菜单项——command 或 submenu 二选一 */
|
|
371
|
+
export type ManifestMenuItem = string | {
|
|
372
|
+
command: string;
|
|
373
|
+
label?: string;
|
|
374
|
+
when?: string;
|
|
375
|
+
group?: string;
|
|
376
|
+
/** E5.8#33:排序权重——同 group 内越小越靠前(壳招牌用于菜单栏组序) */
|
|
377
|
+
order?: number;
|
|
378
|
+
/** E3f #52a:嵌套子菜单——有 children 时 command 可为空 */
|
|
379
|
+
children?: ManifestMenuItem[];
|
|
380
|
+
};
|
|
381
|
+
/** 菜单项描述——menu.getItems() 返回(壳侧 when 过滤 + t() 翻译 + 快捷键解析后) */
|
|
382
|
+
export interface MenuItemDescriptor {
|
|
383
|
+
command: string;
|
|
384
|
+
label?: string;
|
|
385
|
+
group?: string;
|
|
386
|
+
order?: number;
|
|
387
|
+
when?: string;
|
|
388
|
+
/** 壳侧解析后的命令标题(E5.7#14 显示文本铁律) */
|
|
389
|
+
title?: string;
|
|
390
|
+
/** 已解析快捷键 "ctrl+shift+p" 形式 */
|
|
391
|
+
shortcut?: string;
|
|
392
|
+
/** E5.8#37.7:当前项 √ 标记(单选语义——壳侧 getItems 动态解析,VS Code 菜单当前项同款)。
|
|
393
|
+
* 位置/对齐子菜单(当前 edge/align 命中项)+ #37.7.1 视图显隐列表(visible 视图项)共用。 */
|
|
394
|
+
checked?: boolean;
|
|
395
|
+
/**
|
|
396
|
+
* E5.8#37.7.1:每项命令载荷——动态菜单项(如面板视图显隐清单)携带数据传给命令 handler。
|
|
397
|
+
* ContextMenu 的 context 是整菜单共享的(非 per-item),per-item 身份(如 containerId+viewId)
|
|
398
|
+
* 必须走命令载荷:executeCommand(id, undefined, ...commandArgs, context) → 壳 handler 收 args
|
|
399
|
+
* = [...commandArgs, context]。池哑渲染原文透传,不解释内容。
|
|
400
|
+
*/
|
|
401
|
+
commandArgs?: unknown[];
|
|
402
|
+
children?: Array<string | MenuItemDescriptor>;
|
|
403
|
+
}
|
|
404
|
+
/**
|
|
405
|
+
* 对话框 wire 契约——E5.7#97。
|
|
406
|
+
*
|
|
407
|
+
* 曾双份定义:linkdesk-api.ts(E5.7#73 插件侧)与 dialog-handlers.ts 内联结构体
|
|
408
|
+
* 手工对齐——一边改另一边静默失效。本模块一处定义:
|
|
409
|
+
* 插件 API re-export(保持既有 import 路径)+ preload + 主进程三端 import type。
|
|
410
|
+
*/
|
|
411
|
+
export interface DialogOpenOptions {
|
|
412
|
+
title?: string;
|
|
413
|
+
/** true = 选目录,默认选文件 */
|
|
414
|
+
directory?: boolean;
|
|
415
|
+
filters?: {
|
|
416
|
+
name: string;
|
|
417
|
+
extensions: string[];
|
|
418
|
+
}[];
|
|
419
|
+
}
|
|
420
|
+
/** 插件侧条目——对标 VS Code QuickPickItem 三字段(label 第一行左 / description 第一行右 / detail 第二行左) */
|
|
421
|
+
export interface PluginQuickPickItem {
|
|
422
|
+
label: string;
|
|
423
|
+
/** 第一行右 */
|
|
424
|
+
description?: string;
|
|
425
|
+
/** 第二行左 */
|
|
426
|
+
detail?: string;
|
|
427
|
+
}
|
|
428
|
+
/** 插件侧 show() 选项——v1 最小面:items + 输入框占位/前缀(buttons/onHighlight 留待消费方出现) */
|
|
429
|
+
export interface PluginQuickPickOptions {
|
|
430
|
+
items: PluginQuickPickItem[];
|
|
431
|
+
placeholder?: string;
|
|
432
|
+
prefix?: string;
|
|
433
|
+
}
|
|
434
|
+
/**
|
|
435
|
+
* 插件 quickPick 请求——preload show() 经 contextBridge 函数代理桥接给池 QuickPickHost 的形状。
|
|
436
|
+
* 池内本地桥(零 IPC):Promise resolve 的正是 opts.items 里的原对象(身份保持,非序列化副本)。
|
|
437
|
+
*/
|
|
438
|
+
export interface PluginQuickPickRequest {
|
|
439
|
+
opts: PluginQuickPickOptions;
|
|
440
|
+
}
|
|
441
|
+
/** 行内操作按钮——池哑渲染,点击回传 actionId */
|
|
442
|
+
export interface PoolQuickPickButton {
|
|
443
|
+
/** 动作 ID——壳 onItemAction(item, actionId) 执行 */
|
|
444
|
+
actionId: string;
|
|
445
|
+
/** codicon 图标名(不含 "codicon-" 前缀) */
|
|
446
|
+
icon: string;
|
|
447
|
+
tooltip?: string;
|
|
448
|
+
}
|
|
449
|
+
export interface PoolQuickPickItem {
|
|
450
|
+
/** getKey(item)——壳侧动作重解析的唯一键 */
|
|
451
|
+
key: string;
|
|
452
|
+
/** getSearchText(item)——池本地模糊匹配 */
|
|
453
|
+
searchText: string;
|
|
454
|
+
/** E5.8#32:已激活项勾选标记——label 左侧 ✓。undefined = 无勾选(通用 QuickPick 不受影响);true/false = 渲染固定占位保对齐 */
|
|
455
|
+
checked?: boolean;
|
|
456
|
+
/** 第一行左——已 t() 解析 */
|
|
457
|
+
label: string;
|
|
458
|
+
/** 第一行右——已 t() 解析 */
|
|
459
|
+
category?: string;
|
|
460
|
+
/** 第二行左——已 t() 解析 */
|
|
461
|
+
detail?: string;
|
|
462
|
+
/** 快捷键 "ctrl+shift+p" 形式——池渲染 keycap pill(哑) */
|
|
463
|
+
keybinding?: string;
|
|
464
|
+
/** 行内操作按钮 */
|
|
465
|
+
buttons?: PoolQuickPickButton[];
|
|
466
|
+
}
|
|
467
|
+
export interface PoolQuickPickData {
|
|
468
|
+
open: boolean;
|
|
469
|
+
placeholder: string;
|
|
470
|
+
prefix?: string;
|
|
471
|
+
items: PoolQuickPickItem[];
|
|
472
|
+
}
|
|
473
|
+
/** 行内操作按钮——onClick 闭包留在壳,池只回传 actionId(位置序号)。
|
|
474
|
+
* E5.8#20-c:改名 PoolToastButton——与 poolActions.ts PoolToastAction(IPC 回传动作)同名,
|
|
475
|
+
* 契约平铺进单文件会声明合并成幽灵复合型;按钮描述型用 Button 后缀消歧。 */
|
|
476
|
+
export interface PoolToastButton {
|
|
477
|
+
/** 位置序号字符串——壳按 actions[Number(actionId)] 重解析 onClick */
|
|
478
|
+
actionId: string;
|
|
479
|
+
label: string;
|
|
480
|
+
isPrimary?: boolean;
|
|
481
|
+
}
|
|
482
|
+
export interface PoolToastItem {
|
|
483
|
+
id: string;
|
|
484
|
+
message: string;
|
|
485
|
+
/** 壳侧已解析的图标类(codicon + severity 类)——池原样渲染 */
|
|
486
|
+
iconClass: string;
|
|
487
|
+
/** 壳侧已 t() 解析的 "来源: xxx"——池原样渲染 */
|
|
488
|
+
sourceText?: string;
|
|
489
|
+
actions?: PoolToastButton[];
|
|
490
|
+
}
|
|
491
|
+
export interface PoolToastData {
|
|
492
|
+
toasts: PoolToastItem[];
|
|
493
|
+
/** NotificationCenter 打开时壳推 true——池整体隐藏(对标壳 ToastContainer) */
|
|
494
|
+
suppressed: boolean;
|
|
495
|
+
}
|
|
496
|
+
/**
|
|
497
|
+
* Pool Dialog 哑渲染数据——E5.7#17(浮层归一化设计.md §7)。
|
|
498
|
+
*
|
|
499
|
+
* 聪慧→哑数据流:壳 DialogService 桥(renderer 注册)把 options 序列化成 DTO 推送
|
|
500
|
+
* (显示文本铁律——按钮文案已由壳侧 t() 解析,池原样渲染)。
|
|
501
|
+
* Promise 的 resolve 闭包留壳——池只回传动作类型(confirm/cancel),壳侧 settle。
|
|
502
|
+
*/
|
|
503
|
+
export type PoolDialogData = {
|
|
504
|
+
open: false;
|
|
505
|
+
} | {
|
|
506
|
+
open: true;
|
|
507
|
+
title: string;
|
|
508
|
+
message: string;
|
|
509
|
+
/** 壳侧已 t() 解析——池原样渲染 */
|
|
510
|
+
confirmLabel?: string;
|
|
511
|
+
cancelLabel?: string;
|
|
512
|
+
/** alert 模式——只有确定按钮,无取消/Escape/backdrop 关闭 */
|
|
513
|
+
isAlert: boolean;
|
|
514
|
+
};
|
|
515
|
+
/** 标题栏动作按钮——池渲染 + 回传壳侧重解析业务语义(池零语义,UI 机械知识除外)。
|
|
516
|
+
* E5.8#20-c:改名 PoolFloatingPanelButton——与 poolActions.ts PoolFloatingPanelAction(IPC 回传动作)
|
|
517
|
+
* 同名,契约平铺进单文件会声明合并成幽灵复合型;按钮描述型用 Button 后缀消歧(poolToast 同款)。 */
|
|
518
|
+
export interface PoolFloatingPanelButton {
|
|
519
|
+
/** 动作 id——open-in(在主窗口中打开)/ maximize(最大化)/ close(关闭),壳侧重解析 */
|
|
520
|
+
id: string;
|
|
521
|
+
/** 壳 t() 已解析的动作名——mockup:hover tooltip(open-in 展开全文) */
|
|
522
|
+
label: string;
|
|
523
|
+
/** 内建图标 id——池按 id 选 SVG(open-in/maximize/restore/close) */
|
|
524
|
+
icon: string;
|
|
525
|
+
/** 本地 toggle 专用(I8-9 最大化→还原 同按钮)——切换态图标,缺省 = 非 toggle 动作(回传壳) */
|
|
526
|
+
toggledIcon?: string;
|
|
527
|
+
/** 本地 toggle 切换态文案(如「还原」)——池零自产文本,两态文案都壳 t() 给 */
|
|
528
|
+
toggledLabel?: string;
|
|
529
|
+
/** open-in 类型——默认纯图标、hover 展开全文(mockup .fp-act.open-in) */
|
|
530
|
+
expandOnHover?: boolean;
|
|
531
|
+
}
|
|
532
|
+
export type PoolFloatingPanelData = {
|
|
533
|
+
open: false;
|
|
534
|
+
} | {
|
|
535
|
+
open: true;
|
|
536
|
+
/** 面板身份——壳 FloatingPanelService 单实例语义按 viewId 裁决(I8-10:同 viewId 聚焦 / 异 viewId 替换) */
|
|
537
|
+
viewId: string;
|
|
538
|
+
/** 标题——壳 t() 已解析,池原样渲染 */
|
|
539
|
+
title: string;
|
|
540
|
+
/** 内容插件——池经 PluginComponent(pluginId, renderPath) 渲染(壳不持渲染器) */
|
|
541
|
+
pluginId: string;
|
|
542
|
+
/** 内容视图 renderPath——池视图注册表寻址 */
|
|
543
|
+
renderPath: string;
|
|
544
|
+
/** 标题栏动作按钮(顺序 = 渲染顺序:open-in / maximize / close) */
|
|
545
|
+
actions: PoolFloatingPanelButton[];
|
|
546
|
+
/** 语言切换文案重推标记(refreshPanelText)——池仅更新标题/动作渲染,跳过焦点获取(I8-8 首次打开才入焦点) */
|
|
547
|
+
refresh?: boolean;
|
|
548
|
+
};
|
|
549
|
+
/** UI 浮层/菜单/通知命名空间面——对标 VS Code vscode.window + ContextKey + 池内 QuickPick/Toast/Dialog 宿主桥 */
|
|
550
|
+
export interface UiAPI {
|
|
551
|
+
/** 通知——插件弹出壳侧 toast,对标 VS Code vscode.window.showInformationMessage */
|
|
552
|
+
notifications: {
|
|
553
|
+
/** 弹出通知。progress=true 时返回 ProgressHandle(含 update/finish/cancel) */
|
|
554
|
+
show(message: string, options?: {
|
|
555
|
+
type?: "info" | "warning" | "error";
|
|
556
|
+
progress?: boolean;
|
|
557
|
+
}): Promise<NotificationHandle | undefined>;
|
|
558
|
+
};
|
|
559
|
+
/** E5#69:菜单——插件声明式读写 */
|
|
560
|
+
menu: {
|
|
561
|
+
registerItems(menuId: string, pluginId: string, items: ManifestMenuItem[]): Promise<void>;
|
|
562
|
+
getItems(menuId: string, context?: Record<string, unknown>): Promise<MenuItemDescriptor[]>;
|
|
563
|
+
};
|
|
564
|
+
/** E5#70:ContextKey——插件 SET 状态供壳 when 子句读 */
|
|
565
|
+
contextKey: {
|
|
566
|
+
set(key: string, value: unknown): Promise<void>;
|
|
567
|
+
_getValue?(key: string): unknown;
|
|
568
|
+
};
|
|
569
|
+
/** E5#67:弹窗——确认/提示/文件选择 */
|
|
570
|
+
dialog: {
|
|
571
|
+
confirm(message: string): Promise<boolean>;
|
|
572
|
+
alert(message: string): Promise<void>;
|
|
573
|
+
/** 文件/目录选择器——对标 Tauri dialog.open(E5.7#73:openFile 为插件侧规范名,本方法保留给既有消费方) */
|
|
574
|
+
open(opts?: DialogOpenOptions): Promise<string | null>;
|
|
575
|
+
/** 打开文件选择器——返回用户选中路径,取消 → null。安全由主进程控制 */
|
|
576
|
+
openFile(opts?: DialogOpenOptions): Promise<string | null>;
|
|
577
|
+
};
|
|
578
|
+
/** E5.7#63:插件 quickPick 选择器——池内本地桥(零 IPC,QuickPickHost 渲染)。结算 null → undefined */
|
|
579
|
+
quickPick: {
|
|
580
|
+
show(opts: PluginQuickPickOptions): Promise<unknown>;
|
|
581
|
+
};
|
|
582
|
+
/** E5.7#63:QuickPick 宿主渲染桥——池 QuickPickHost 消费(壳 preload 无此面) */
|
|
583
|
+
quickPickHost: {
|
|
584
|
+
registerHost(fn: (req: PluginQuickPickRequest, settle: (key: string | null) => void) => void): () => void;
|
|
585
|
+
onShow(cb: (data: PoolQuickPickData) => void): () => void;
|
|
586
|
+
select(key: string): void;
|
|
587
|
+
highlight(key: string): void;
|
|
588
|
+
close(): void;
|
|
589
|
+
itemAction(key: string, actionId: string): void;
|
|
590
|
+
};
|
|
591
|
+
/** E5.7#16:Toast 哑渲染订阅——池 ToastHost 消费(壳 preload 无此面) */
|
|
592
|
+
toast: {
|
|
593
|
+
onShow(cb: (data: PoolToastData) => void): () => void;
|
|
594
|
+
dismiss(id: string): void;
|
|
595
|
+
action(id: string, actionId: string): void;
|
|
596
|
+
};
|
|
597
|
+
/** E5.7#17:Dialog 哑渲染订阅——池 DialogHost 消费(壳 preload 无此面)。命名 dialogHost——
|
|
598
|
+
* dialog 命名空间已是插件侧 confirm/alert/open API */
|
|
599
|
+
dialogHost: {
|
|
600
|
+
onShow(cb: (data: PoolDialogData) => void): () => void;
|
|
601
|
+
confirm(): void;
|
|
602
|
+
cancel(): void;
|
|
603
|
+
};
|
|
604
|
+
/** E5.8#37(Phase 8 类型 B):悬浮面板哑渲染订阅——池 FloatingPanelHost 消费(壳 preload 无此面)。
|
|
605
|
+
* 命名 floatingPanelHost——面板请求 API(panel.revealFloating)归 PanelAPI,宿主渲染桥归本面 */
|
|
606
|
+
floatingPanelHost: {
|
|
607
|
+
onShow(cb: (data: PoolFloatingPanelData) => void): () => void;
|
|
608
|
+
/** 动作回传——open-in(在主窗口中打开)/ close,壳侧 settle(业务语义壳侧重解析) */
|
|
609
|
+
action(actionId: string): void;
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
/** 端口列表条目——listPorts() 返回 */
|
|
613
|
+
export interface SerialPortInfo {
|
|
614
|
+
name: string;
|
|
615
|
+
description: string;
|
|
616
|
+
}
|
|
617
|
+
/** 串口状态快照——F5 刷新 / getStatus() 返回 */
|
|
618
|
+
export interface SerialStatus {
|
|
619
|
+
isOpen: boolean;
|
|
620
|
+
portName: string;
|
|
621
|
+
baudRate: number;
|
|
622
|
+
}
|
|
623
|
+
/** 打开串口配置——插件 API 入参 + 主进程 serial-service 消费 */
|
|
624
|
+
export interface OpenPortConfig {
|
|
625
|
+
portName: string;
|
|
626
|
+
baudRate: number;
|
|
627
|
+
dataBits?: number;
|
|
628
|
+
stopBits?: number;
|
|
629
|
+
parity?: string;
|
|
630
|
+
encoding?: string;
|
|
631
|
+
/** E5.8#26 D8——资源归属声明:由插件 openPort 时自声明(pool WCV 多插件同 JS 上下文,
|
|
632
|
+
* 主进程无法从 sender 识别插件),卸载时 closePortsByOwner 按此回收硬件资源。 */
|
|
633
|
+
ownerPluginId?: string;
|
|
634
|
+
}
|
|
635
|
+
/** 串口数据载荷——serial.data 推送(E5.8#28:由原无口名 string 演化——D6 载荷对象化)。 */
|
|
636
|
+
export interface SerialDataPayload {
|
|
637
|
+
/** 数据源端口 = 路由键——消费方按 portName 收自己的口的数据(多口并存各口各收) */
|
|
638
|
+
portName: string;
|
|
639
|
+
/** 解码后的行文本 */
|
|
640
|
+
text: string;
|
|
641
|
+
}
|
|
642
|
+
/** 串口统计载荷——serial.stats 推送(E5.8#28:由原无口名 SerialStats 演化——S10 每口计数器的数据源)。
|
|
643
|
+
* tx/rx 为推送增量(非累计值)——消费方自行累加。 */
|
|
644
|
+
export interface SerialStatsPayload {
|
|
645
|
+
/** 统计归属端口 = 路由键——各口计数器独立累加 */
|
|
646
|
+
portName: string;
|
|
647
|
+
tx?: number;
|
|
648
|
+
rx?: number;
|
|
649
|
+
}
|
|
650
|
+
/** 串口系统消息载荷——serial.system 推送(E5.8#28:由原无口名 string 演化——S12 正则挖口名 hack 的修根)。
|
|
651
|
+
* message 保留 V2 消息格式(如 `---- 已打开串行端口 COM3 ----`),portName 结构化免解析。
|
|
652
|
+
* E5.8#30.11(P1)——type 分类标签(审视 ①:来源端分类,一个概念一处写,不做消费端文案关键词判断):
|
|
653
|
+
* status = 正常成功流程(开/关/波特率切换);error = 非正常流程(同口二开拒绝 D8 / 驱动错误 / 拔线)。
|
|
654
|
+
* 消费端按键路由:status 按口过滤(他口操作不显示)、error 全局可见(非活动标签页也显示)。 */
|
|
655
|
+
export interface SerialSystemPayload {
|
|
656
|
+
/** 消息归属端口 = 路由键——本端口会话专属消费(开/关状态切换);不匹配的会话仍可显示文本但不触发状态切换 */
|
|
657
|
+
portName: string;
|
|
658
|
+
message: string;
|
|
659
|
+
/** 消息分类——status 成功流程 / error 失败异常(D8 拒绝、驱动错误、拔线) */
|
|
660
|
+
type: "status" | "error";
|
|
661
|
+
}
|
|
662
|
+
/** 串口/剪贴板/插件间通信/事件/持久化存储命名空间面——对标 VS Code SerialPort API + p2p + EventEmitter + state */
|
|
663
|
+
export interface DataAPI {
|
|
664
|
+
/** 串口——读/写/监听,对标 VS Code SerialPort API */
|
|
665
|
+
serial: {
|
|
666
|
+
listPorts(): Promise<SerialPortInfo[]>;
|
|
667
|
+
/** E5.8#26 D5 双形态:无参 → SerialStatus[](全部打开口,空数组 = 全关)/ 有参 → 单口快照(F5 遍历恢复用) */
|
|
668
|
+
getStatus(): Promise<SerialStatus[]>;
|
|
669
|
+
getStatus(portName: string): Promise<SerialStatus>;
|
|
670
|
+
openPort(cfg: OpenPortConfig): Promise<void>;
|
|
671
|
+
/** E5.8#26 D2——portName 可选:缺省 = 唯一打开口(0 口抛「串口未打开」/ ≥2 口抛「多串口已打开,请指定 portName」) */
|
|
672
|
+
closePort(portName?: string): Promise<void>;
|
|
673
|
+
sendData(data: number[], portName?: string): Promise<void>;
|
|
674
|
+
sendText(text: string, enc: string, portName?: string): Promise<void>;
|
|
675
|
+
setDtr(enable: boolean, portName?: string): Promise<void>;
|
|
676
|
+
setRts(enable: boolean, portName?: string): Promise<void>;
|
|
677
|
+
/** E5.8#28:载荷对象化——SerialDataPayload.portName = 路由键(多口并存各口各收) */
|
|
678
|
+
onData(cb: (payload: SerialDataPayload) => void): () => void;
|
|
679
|
+
onStats(cb: (payload: SerialStatsPayload) => void): () => void;
|
|
680
|
+
onSystem(cb: (payload: SerialSystemPayload) => void): () => void;
|
|
681
|
+
};
|
|
682
|
+
/** 剪贴板——读/写系统剪贴板 */
|
|
683
|
+
clipboard: {
|
|
684
|
+
readText(): Promise<string>;
|
|
685
|
+
writeText(text: string): Promise<void>;
|
|
686
|
+
/** 写入文件列表——文件树复制粘贴用 */
|
|
687
|
+
writeFileList(paths: string[]): Promise<void>;
|
|
688
|
+
};
|
|
689
|
+
/** E5#65:p2p 插件间定向推流——和 bridge.broadcast 同模式(fire-and-forget) */
|
|
690
|
+
p2p: {
|
|
691
|
+
send(target: string, channel: string, data: unknown): void;
|
|
692
|
+
on(channel: string, cb: (data: unknown) => void): () => void;
|
|
693
|
+
};
|
|
694
|
+
/** 通用事件订阅 + 发布——插件间数据管道。channel 为自由字符串,载荷按通道分型——订阅方收窄 */
|
|
695
|
+
events: {
|
|
696
|
+
/** E5.7#98:on 泛型化——载荷类型按订阅方 cb 推断(event-system EventSystemApi 同款,#97 已泛型化 impl),通道契约类型(ConfigurationChangedPayload 等)可直传 */
|
|
697
|
+
on<T = unknown>(channel: string, cb: (payload: T) => void): () => void;
|
|
698
|
+
emit(channel: string, payload: unknown): void;
|
|
699
|
+
heartbeat?(): void;
|
|
700
|
+
notifyTheme?(isDark: boolean): void;
|
|
701
|
+
};
|
|
702
|
+
/** E5#71:插件持久化存储——集中缓存 + 文件持久化 */
|
|
703
|
+
pluginState: {
|
|
704
|
+
/** 读取持久化状态——运行时动态值,默认 unknown;调用方显式 get<string>(...) 窄化或自行收窄 */
|
|
705
|
+
get<T = unknown>(pluginId: string, key: string): Promise<T | undefined>;
|
|
706
|
+
set(pluginId: string, key: string, value: unknown): Promise<void>;
|
|
707
|
+
/** 订阅持久化状态变更——按 pluginId+key 精确匹配(通配键名订阅走 events.on("plugin-state:changed"),见 E5.8#20 补导出 PluginStateChangedPayload)。返回 unsubscribe */
|
|
708
|
+
onChange(pluginId: string, key: string, cb: (value: unknown) => void): () => void;
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
export interface WorkspaceFolder {
|
|
712
|
+
/** 文件夹完整路径(file:// URI) */
|
|
713
|
+
uri: string;
|
|
714
|
+
/** 文件夹名——路径最后一段 */
|
|
715
|
+
name: string;
|
|
716
|
+
/** 索引——第一个打开的文件夹 index=0 */
|
|
717
|
+
index: number;
|
|
718
|
+
}
|
|
719
|
+
/** 文件/目录条目——前后端共用 */
|
|
720
|
+
export interface FileEntry {
|
|
721
|
+
name: string;
|
|
722
|
+
path: string;
|
|
723
|
+
isDirectory: boolean;
|
|
724
|
+
isFile: boolean;
|
|
725
|
+
size?: number; // 字节
|
|
726
|
+
modifiedAt?: number; // Unix 时间戳 ms
|
|
727
|
+
/** E4V#10: 文件是否只读(不可写) */
|
|
728
|
+
isReadonly?: boolean;
|
|
729
|
+
}
|
|
730
|
+
export interface FileChangeEvent {
|
|
731
|
+
path: string;
|
|
732
|
+
type: "created" | "changed" | "deleted";
|
|
733
|
+
}
|
|
734
|
+
/** 环境信息——env.get() 返回(主进程 env-handlers 组装) */
|
|
735
|
+
export interface EnvInfo {
|
|
736
|
+
appDataDir: string;
|
|
737
|
+
pluginsRootDir: string;
|
|
738
|
+
appPluginsDir: string;
|
|
739
|
+
pluginDataDir?: string;
|
|
740
|
+
pluginCacheDir?: string;
|
|
741
|
+
pluginExportsDir?: string;
|
|
742
|
+
}
|
|
743
|
+
/** IPC search:searchFiles 载荷——FileSearcher.SearchOptions 的 wire 子集(无 signal) */
|
|
744
|
+
export interface SearchWireOptions {
|
|
745
|
+
roots: string[];
|
|
746
|
+
query: string;
|
|
747
|
+
include?: string;
|
|
748
|
+
exclude?: string;
|
|
749
|
+
caseSensitive?: boolean;
|
|
750
|
+
wholeWord?: boolean;
|
|
751
|
+
useRegex?: boolean;
|
|
752
|
+
maxResults?: number;
|
|
753
|
+
}
|
|
754
|
+
/** 单个匹配——1-based lineNumber;matchStart/matchEnd 为该行内 0-based 列区间(不含 end) */
|
|
755
|
+
export interface SearchWireMatch {
|
|
756
|
+
filePath: string;
|
|
757
|
+
lineNumber: number;
|
|
758
|
+
lineText: string;
|
|
759
|
+
matchStart: number;
|
|
760
|
+
matchEnd: number;
|
|
761
|
+
}
|
|
762
|
+
/** IPC search:searchFiles 返回——FileSearchResult 的 wire 形状 */
|
|
763
|
+
export type SearchWireResult = Array<{
|
|
764
|
+
filePath: string;
|
|
765
|
+
matches: SearchWireMatch[];
|
|
766
|
+
}>;
|
|
767
|
+
/** 工作区/文件系统/路径/环境/搜索/编码命名空间面——对标 VS Code vscode.workspace + env + ExtensionContext */
|
|
768
|
+
export interface WorkspaceAPI {
|
|
769
|
+
/** 工作区——池 preload 注入(壳侧经 WorkspaceService 直用)。池权威命名空间——插件必用面(file-tree),必选 */
|
|
770
|
+
workspace: {
|
|
771
|
+
getFolders(): Promise<WorkspaceFolder[]>;
|
|
772
|
+
getActive(): Promise<string | undefined>;
|
|
773
|
+
setActive(uri: string): Promise<void>;
|
|
774
|
+
openFolder(): Promise<void>;
|
|
775
|
+
addFolder(path: string): Promise<void>;
|
|
776
|
+
removeFolder(path: string): Promise<void>;
|
|
777
|
+
onDidChangeFolders(cb: () => void): () => void;
|
|
778
|
+
onDidChangeActiveWorkspace(cb: (uri: string | null) => void): () => void;
|
|
779
|
+
};
|
|
780
|
+
/** 文件系统——插件读写(路径校验由主进程执行) */
|
|
781
|
+
filesystem: {
|
|
782
|
+
readTextFile(p: string): Promise<string>;
|
|
783
|
+
writeTextFile(p: string, d: string): Promise<void>;
|
|
784
|
+
exists(p: string): Promise<boolean>;
|
|
785
|
+
createDir(p: string): Promise<void>;
|
|
786
|
+
copy(src: string, dest: string): Promise<void>;
|
|
787
|
+
/** E5.8#25.2:重命名/移动文件或目录(主进程 fs.rename 原子;对标 POSIX rename / VS Code fs.rename) */
|
|
788
|
+
rename(src: string, dest: string): Promise<void>;
|
|
789
|
+
remove(p: string): Promise<void>;
|
|
790
|
+
listDir(p: string): Promise<FileEntry[]>;
|
|
791
|
+
readBinaryFile(p: string): Promise<Uint8Array>;
|
|
792
|
+
writeBinaryFile(p: string, d: Uint8Array): Promise<void>;
|
|
793
|
+
/** 监听目录变更——返回 unsubscribe(内部走 filesystem:changed:<watcherId> 通道) */
|
|
794
|
+
watch(dirPath: string, onEvent: (e: FileChangeEvent) => void): Promise<() => void>;
|
|
795
|
+
/** 列出条目名——壳 preload 独有(池侧请用 listDir) */
|
|
796
|
+
readdir?(p: string): Promise<string[]>;
|
|
797
|
+
};
|
|
798
|
+
/** 路径工具——壳/池双端注入(editor/file-tree 池插件消费 normalize/join 等);appDataDir 双端同款(E5.8#0d.5:池侧补上——settings 插件池内解析 userData 路径) */
|
|
799
|
+
path: {
|
|
800
|
+
appDataDir?(): Promise<string>;
|
|
801
|
+
normalize(p: string): string;
|
|
802
|
+
join(...parts: string[]): string;
|
|
803
|
+
basename(p: string): string;
|
|
804
|
+
dirname(p: string): string;
|
|
805
|
+
extname(p: string): string;
|
|
806
|
+
};
|
|
807
|
+
/** 环境信息——对标 VS Code ExtensionContext */
|
|
808
|
+
env: {
|
|
809
|
+
get(pluginId?: string): Promise<EnvInfo>;
|
|
810
|
+
};
|
|
811
|
+
/** E5.6#11.5a:文件搜索——全文搜索/替换(IPC 到壳/主进程执行) */
|
|
812
|
+
search: {
|
|
813
|
+
// E5.8#1c:wire 契约归口 src/core/types/ipc/search.ts——与 preload-pool buildSearch 双端同源
|
|
814
|
+
searchFiles(opts: SearchWireOptions): Promise<SearchWireResult>;
|
|
815
|
+
};
|
|
816
|
+
/** E5.6#11.5a:编码检测/转换(主进程 EncodingService) */
|
|
817
|
+
encoding: {
|
|
818
|
+
detect(buffer: Uint8Array): Promise<string>;
|
|
819
|
+
decode(buffer: Uint8Array, encoding: string): Promise<string>;
|
|
820
|
+
encode(text: string, encoding: string): Promise<Uint8Array>;
|
|
821
|
+
};
|
|
822
|
+
}
|
|
823
|
+
/** 文件装饰——E5.7#60 池内本地注册表。形状对标插件 API 契约 §3.24 */
|
|
824
|
+
export interface FileDecoration {
|
|
825
|
+
badge?: string;
|
|
826
|
+
tooltip?: string;
|
|
827
|
+
color?: string;
|
|
828
|
+
propagate?: boolean;
|
|
829
|
+
}
|
|
830
|
+
/** 文件装饰提供方——插件注册(registerProvider)。同步查询契约:跳过返回 Promise 的 provideDecoration */
|
|
831
|
+
export interface FileDecorationProvider {
|
|
832
|
+
provideDecoration(uri: string): FileDecoration | null | undefined;
|
|
833
|
+
onDidChangeFileDecorations?(cb: (uris: string[]) => void): () => void;
|
|
834
|
+
}
|
|
835
|
+
/** 文件装饰/关联/语言定义/LSP/协议/视图容器命名空间面——编辑器配套服务(主进程/池内直答) */
|
|
836
|
+
export interface EditorAPI {
|
|
837
|
+
/** E5.7#60:文件装饰——池内本地注册表(零 IPC)。形状对标契约 §3.24 */
|
|
838
|
+
decorations: {
|
|
839
|
+
registerProvider(pluginId: string, provider: FileDecorationProvider): void;
|
|
840
|
+
unregisterProvider(pluginId: string): void;
|
|
841
|
+
getDecoration(uri: string): Promise<FileDecoration | null>;
|
|
842
|
+
onDidChange(cb: (uris: string[]) => void): () => void;
|
|
843
|
+
};
|
|
844
|
+
/** E5.7#50:文件关联——扩展名→插件 ID(主进程 FileAssociationService 直答) */
|
|
845
|
+
fileAssociation: {
|
|
846
|
+
getPluginFor(ext: string): Promise<string | undefined>;
|
|
847
|
+
};
|
|
848
|
+
/** E5.7#49:langDef——语言定义注册表(主进程直答)。只返回可序列化字段(monarch tokenizer 函数主进程侧剥壳) */
|
|
849
|
+
langDef: {
|
|
850
|
+
get(extension: string): Promise<{
|
|
851
|
+
id: string;
|
|
852
|
+
lsp?: {
|
|
853
|
+
command: string;
|
|
854
|
+
args?: string[];
|
|
855
|
+
};
|
|
856
|
+
} | null>;
|
|
857
|
+
};
|
|
858
|
+
/** E5.6#14-lsp:LSP 桥——自动补全/F12/诊断/重命名 */
|
|
859
|
+
lsp: {
|
|
860
|
+
spawn(command: string, args: string[] | undefined, pluginId: string): Promise<string>;
|
|
861
|
+
write(channelId: string, data: string): void;
|
|
862
|
+
dispose(channelId: string): Promise<unknown>;
|
|
863
|
+
onData(cb: (channelId: string, data: string) => void): () => void;
|
|
864
|
+
};
|
|
865
|
+
/** E5.7#49:protocol——协议注册表(主进程直答)。返回前剥 parseLine/detect(JS 函数不可跨进程) */
|
|
866
|
+
protocol: {
|
|
867
|
+
listProtocols(): Promise<Array<{
|
|
868
|
+
id: string;
|
|
869
|
+
name: string;
|
|
870
|
+
pluginId: string;
|
|
871
|
+
mode: string;
|
|
872
|
+
}>>;
|
|
873
|
+
getActiveProtocolId(): Promise<string>;
|
|
874
|
+
setActiveProtocolId(protocolId: string): Promise<void>;
|
|
875
|
+
};
|
|
876
|
+
/** E5.7#58:viewContainer——真 IPC 查询/更新(问壳侧注册表)。DTO 只含可序列化公开字段 */
|
|
877
|
+
viewContainer: {
|
|
878
|
+
getViewContainer(id: string): Promise<Record<string, unknown> | undefined>;
|
|
879
|
+
getViews(containerId: string): Promise<Array<Record<string, unknown>>>;
|
|
880
|
+
// E5.8#41.9.2:getView 复合寻址——(pluginId, viewId) 精确查视图元数据(#41.8 碰撞面 #2)
|
|
881
|
+
getView(pluginId: string, viewId: string): Promise<Record<string, unknown> | undefined>;
|
|
882
|
+
registerView(pluginId: string, containerId: string, descriptor: Record<string, unknown>): Promise<void>;
|
|
883
|
+
};
|
|
884
|
+
}
|
|
885
|
+
/**
|
|
886
|
+
* Phase 4 核心类型定义。
|
|
887
|
+
* 插件元数据、标签页扩展字段、视图注册表条目。
|
|
888
|
+
*
|
|
889
|
+
* 设计依据:[[phase4-design-decisions]] + public/schemas/plugin.schema.json
|
|
890
|
+
*/
|
|
891
|
+
export type PluginType = "view" | "card" | "theme" | "language" | "protocol" | "resource" | "datasource";
|
|
892
|
+
export interface TabBehavior {
|
|
893
|
+
/** 场上无标签页时自动创建此标签页,且不可关闭。只有欢迎页声明。 */
|
|
894
|
+
isFallback?: boolean;
|
|
895
|
+
/** 全局只允许一个实例,重复创建 → 聚焦已有。如设置页。 */
|
|
896
|
+
singleton?: boolean;
|
|
897
|
+
/** 关闭前弹确认框,值为提示文本。如终端。 */
|
|
898
|
+
confirmOnClose?: string;
|
|
899
|
+
/** 关闭前调用的 Tauri invoke 命令(在 confirmOnClose 确认之后,closeTab 之前)。如终端声明 "close_port"。 */
|
|
900
|
+
invokeBeforeClose?: string;
|
|
901
|
+
/** CreateTabOptions 中用于判断标签页身份的唯一字段。null=允许多实例不去重(默认)。
|
|
902
|
+
* 如 workspace 声明 "workspaceName"——同名工作台只允许一个标签页。 */
|
|
903
|
+
identityField?: string;
|
|
904
|
+
}
|
|
905
|
+
export interface StatusBarItem {
|
|
906
|
+
id: string;
|
|
907
|
+
icon?: string;
|
|
908
|
+
label: string;
|
|
909
|
+
align?: "left" | "right";
|
|
910
|
+
onClick?: string;
|
|
911
|
+
/** 声明 true → 壳自动注册配置项(<pluginId>.statusBar.<id>)+ 注入 visible prop。
|
|
912
|
+
* 插件作者只写一行 JSON,用户可在 Settings Editor 开关。 */
|
|
913
|
+
configurable?: boolean;
|
|
914
|
+
}
|
|
915
|
+
export interface PluginManifest {
|
|
916
|
+
$schema?: string;
|
|
917
|
+
/** @deprecated 使用 contributes + tabBehavior 等声明字段代替——贡献点由 manifest 的实际声明字段检测(对标 VS Code contributes) */
|
|
918
|
+
type?: PluginType;
|
|
919
|
+
core?: boolean;
|
|
920
|
+
/** 插件角色——只管加载策略。view=有 UI 组件,data=纯数据。不填自动推导 */
|
|
921
|
+
pluginRole?: "view" | "data";
|
|
922
|
+
name: string;
|
|
923
|
+
version: string;
|
|
924
|
+
icon?: string;
|
|
925
|
+
iconSource?: "codicon" | "svg" | "url" | "lucide";
|
|
926
|
+
description?: string;
|
|
927
|
+
author?: string;
|
|
928
|
+
entry?: string;
|
|
929
|
+
sidebar?: string;
|
|
930
|
+
tabBehavior?: TabBehavior;
|
|
931
|
+
/** 系统插槽角色——声明此插件填充哪个系统级功能。settings=设置页,marketplace=插件市场。
|
|
932
|
+
* 多个插件声明同一 role → 第一个 core: true 的胜出。
|
|
933
|
+
* E5.7#65:开放 string——第三方可声明新角色名,壳零改动(FactorySlots 按字符串查表)。 */
|
|
934
|
+
factoryRole?: string;
|
|
935
|
+
statusBar?: StatusBarItem[];
|
|
936
|
+
/** @deprecated E5#12——已迁移到 contributes.themes。仅 normalizeManifest 向后兼容用。 */
|
|
937
|
+
file?: string;
|
|
938
|
+
/** @deprecated E5#12——已迁移到 contributes.themes。仅 normalizeManifest 向后兼容用。 */
|
|
939
|
+
themes?: {
|
|
940
|
+
id: string;
|
|
941
|
+
name: string;
|
|
942
|
+
file: string;
|
|
943
|
+
}[];
|
|
944
|
+
/** @deprecated E5#12——已迁移到 contributes.languages。仅 normalizeManifest 向后兼容用。 */
|
|
945
|
+
languages?: {
|
|
946
|
+
code: string;
|
|
947
|
+
name: string;
|
|
948
|
+
file: string;
|
|
949
|
+
}[];
|
|
950
|
+
mode?: "text" | "binary";
|
|
951
|
+
resources?: string[];
|
|
952
|
+
recommends?: {
|
|
953
|
+
plugin: string;
|
|
954
|
+
reason: string;
|
|
955
|
+
}[];
|
|
956
|
+
suggests?: {
|
|
957
|
+
plugin: string;
|
|
958
|
+
reason: string;
|
|
959
|
+
}[];
|
|
960
|
+
/** 插件级激活顺序依赖(E5.8#13)——按 pluginId 声明,loader 先加载依赖再加载本插件。
|
|
961
|
+
* 纯声明:无版本约束(版本语义属 E6 市场范畴,激活顺序不承载);缺依赖 → loader 状态机挂 PENDING。
|
|
962
|
+
* 与 ConfigurationRegistry 的配置项级 dependsOn(同一 manifest 内某配置项依赖另一配置项)不同域。 */
|
|
963
|
+
requires?: string[];
|
|
964
|
+
changelog?: {
|
|
965
|
+
version: string;
|
|
966
|
+
date: string;
|
|
967
|
+
changes?: string[];
|
|
968
|
+
}[];
|
|
969
|
+
screenshots?: string[];
|
|
970
|
+
minAppVersion?: string;
|
|
971
|
+
/** 激活事件——对标 VS Code activationEvents。空或含 "*" = 启动时立即加载。
|
|
972
|
+
* 具体事件:onCommand:id / onFileOpen:.ext / onPortOpen / onLanguage:id / onView:id */
|
|
973
|
+
activationEvents?: string[];
|
|
974
|
+
/** @deprecated E5.8#14——归并到 requires(插件级激活依赖统一由 requires 声明)。
|
|
975
|
+
* 零插件使用;loader 兼容读取直到 #14 落地迁移。 */
|
|
976
|
+
extensionDependencies?: string[];
|
|
977
|
+
docs?: string;
|
|
978
|
+
cardDocMap?: Record<string, string>;
|
|
979
|
+
/** @deprecated E5#109——使用 contributes.i18n 代替。每插件 `i18n/{lang}.json`,key=中文原文。见 [[i18n-round2-leftovers]] */
|
|
980
|
+
i18n?: Record<string, string>;
|
|
981
|
+
cssVars?: Record<string, {
|
|
982
|
+
dark: string;
|
|
983
|
+
light: string;
|
|
984
|
+
}>;
|
|
985
|
+
permissions?: ("serial" | "filesystem" | "network")[];
|
|
986
|
+
/**
|
|
987
|
+
* Phase 5g:视图元数据——声明视图和壳的交互方式。
|
|
988
|
+
* 这些字段替代 Phase 3/4 的硬编码特殊判断(isSidebarOnlyView / BOTTOM_ICONS 等)。
|
|
989
|
+
*/
|
|
990
|
+
/** 插件 UI 出现位置——声明式。替代 iconLocation + viewRole + keepSidebarOnFocus。
|
|
991
|
+
* 对标 VS Code:viewsContainers + views 的组合推导出 Activity Bar / Sidebar / Panel */
|
|
992
|
+
appearsIn?: {
|
|
993
|
+
iconBar?: "top" | "bottom";
|
|
994
|
+
sidePanel?: boolean;
|
|
995
|
+
tabBar?: boolean;
|
|
996
|
+
statusBar?: boolean;
|
|
997
|
+
};
|
|
998
|
+
/** @deprecated E5#14——用 appearsIn.iconBar 替代。仅 viewRegistry.ts 向后兼容兜底。 */
|
|
999
|
+
iconLocation?: "top" | "bottom";
|
|
1000
|
+
/** @deprecated E5#14——用 appearsIn.tabBar / appearsIn.sidePanel 替代。 */
|
|
1001
|
+
viewRole?: "sidebarPrimary" | "tabOnly";
|
|
1002
|
+
/** @deprecated E2c #19d 后已无 shellRendered 概念——壳级视图直接写 App.tsx,不走 plugin.json 声明。保留仅用于向后兼容。 */
|
|
1003
|
+
shellRendered?: boolean;
|
|
1004
|
+
/** @deprecated E5#14——appearsIn 归一化后不再需要。 */
|
|
1005
|
+
keepSidebarOnFocus?: boolean;
|
|
1006
|
+
/**
|
|
1007
|
+
* Phase 5:对标 VS Code package.json contributes。
|
|
1008
|
+
* 使用 Record<string, unknown> 兼容未知 key——parseContributions 按 key 逐项检测。
|
|
1009
|
+
* 已知 key 的类型见下方 ContributesViewsContainers / ContributesViews。
|
|
1010
|
+
*/
|
|
1011
|
+
contributes?: Record<string, unknown>;
|
|
1012
|
+
}
|
|
1013
|
+
/** list() 的 manifest 序列化子集——与 handlePluginsCall "list" 7 字段对齐 */
|
|
1014
|
+
export interface PluginListSubset {
|
|
1015
|
+
name?: string;
|
|
1016
|
+
description?: string;
|
|
1017
|
+
version?: string;
|
|
1018
|
+
core?: boolean;
|
|
1019
|
+
author?: string;
|
|
1020
|
+
statusBar?: PluginManifest["statusBar"];
|
|
1021
|
+
contributes?: PluginManifest["contributes"];
|
|
1022
|
+
}
|
|
1023
|
+
/** 插件列表条目——pluginManager.list() 返回(主进程序列化后的 manifest 子集)。
|
|
1024
|
+
* E5.7#98:Partial<PluginManifest> 过宽(component 等字段 IPC 不可达)——收窄为
|
|
1025
|
+
* IpcBridgeHandler.handlePluginsCall "list" 分支实际序列化的 7 字段,marketplace 消费。
|
|
1026
|
+
* E5.8#15.5:pendingReason——缺依赖挂起原因("等待依赖: xxx");无挂起 = undefined。
|
|
1027
|
+
* 有值 = 插件已安装但依赖未就绪(PENDING),列表/详情显示等待状态。 */
|
|
1028
|
+
export interface PluginListEntry {
|
|
1029
|
+
pluginId: string;
|
|
1030
|
+
manifest: PluginListSubset;
|
|
1031
|
+
/** 缺依赖挂起原因——marketplace 显示 PENDING 徽标 + 详情提示条(E5.8#15.5) */
|
|
1032
|
+
pendingReason?: string;
|
|
1033
|
+
}
|
|
1034
|
+
/** E5.7#81:安装结果——success:false 时 error 为中文失败原因(校验 / 版本冲突 / 复制失败)。
|
|
1035
|
+
* 安装进度事件:events.on("plugin:installProgress", ({ stage, pluginId, message }) => ...)
|
|
1036
|
+
* stage: validating | copying | loading | done | error
|
|
1037
|
+
* E5.7#83:装卸广播(壳 loader → 唯一 Pool):
|
|
1038
|
+
* events.on("plugin:installed", ({ pluginId, version, reason }) => ...) reason: install | reinstall
|
|
1039
|
+
* events.on("plugin:uninstalled", ({ pluginId, reason }) => ...) reason: uninstall */
|
|
1040
|
+
export interface PluginInstallResult {
|
|
1041
|
+
success: boolean;
|
|
1042
|
+
pluginId?: string;
|
|
1043
|
+
version?: string;
|
|
1044
|
+
needRestart?: boolean;
|
|
1045
|
+
error?: string;
|
|
1046
|
+
}
|
|
1047
|
+
/** 禁用/卸载列表条目——loader getDisabledPluginInfo/getUninstalledPluginInfo 序列化形状(PluginListSubset 的再子集) */
|
|
1048
|
+
export interface PluginInfoEntry {
|
|
1049
|
+
pluginId: string;
|
|
1050
|
+
name: string;
|
|
1051
|
+
description?: string;
|
|
1052
|
+
version?: string;
|
|
1053
|
+
}
|
|
1054
|
+
/** 插件发现/管理命名空间面——桥接 IpcBridgeHandler → loader 函数 */
|
|
1055
|
+
export interface PluginsAPI {
|
|
1056
|
+
/** 插件发现——双端注入:resolvePath 双端同面;读面(listDirs/listDisabledDirs/readManifest)壳 preload 独有(loader 只在壳跑) */
|
|
1057
|
+
plugins: {
|
|
1058
|
+
resolvePath(id: string): Promise<string>;
|
|
1059
|
+
listDirs?(): Promise<string[]>;
|
|
1060
|
+
listDisabledDirs?(): Promise<string[]>;
|
|
1061
|
+
/** 返回 plugin.json 原始 JSON 文本——消费方自行 JSON.parse */
|
|
1062
|
+
readManifest?(id: string): Promise<string>;
|
|
1063
|
+
};
|
|
1064
|
+
/** 插件管理——桥接 IpcBridgeHandler → loader 函数。池权威(marketplace 插件消费),必选 */
|
|
1065
|
+
pluginManager: {
|
|
1066
|
+
list(): Promise<PluginListEntry[]>;
|
|
1067
|
+
enable(id: string): Promise<unknown>;
|
|
1068
|
+
disable(id: string): Promise<unknown>;
|
|
1069
|
+
uninstall(id: string): Promise<unknown>;
|
|
1070
|
+
install(path: string): Promise<PluginInstallResult>;
|
|
1071
|
+
reinstall(id: string): Promise<unknown>;
|
|
1072
|
+
getDisabled(): Promise<PluginInfoEntry[]>;
|
|
1073
|
+
getUninstalled(): Promise<PluginInfoEntry[]>;
|
|
1074
|
+
isDisabled(id: string): Promise<boolean>;
|
|
1075
|
+
/** E5.7#48:装/卸/重装成功 → 通知主进程全量重扫三表 */
|
|
1076
|
+
notifyManifestChanged?(): void;
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* bridge 请求信封契约——E5.7#97。
|
|
1081
|
+
*
|
|
1082
|
+
* 插件 IPC 请求经主进程转发到壳侧服务(IpcBridgeHandler)的信封:
|
|
1083
|
+
* requestId 用于 respond 关联,args 是命令自定参数(shell 侧 switch 收窄)。
|
|
1084
|
+
* preload-shell 的 IpcRelay 缓冲 + IpcBridgeHandler onRequest 同用此型。
|
|
1085
|
+
*/
|
|
1086
|
+
export interface BridgeRequestPayload {
|
|
1087
|
+
requestId: string;
|
|
1088
|
+
channel: string;
|
|
1089
|
+
args: unknown[];
|
|
1090
|
+
/**
|
|
1091
|
+
* E5.8#46.12:信封来源窗盖章——主进程按 sender 反查 windowId(池不知自身 windowId,#43-4 铁律),
|
|
1092
|
+
* 池→壳每一请求自带来源窗身份。壳按此路由按窗操作(sourceId 族:标签改/关/聚焦落到来源窗注册表,
|
|
1093
|
+
* 主窗照旧)——窗口身份丢失类(黑点/面板/弹窗)同根归一化。壳侧 switch 收窄时按需消费,无消费方忽略。
|
|
1094
|
+
*/
|
|
1095
|
+
sourceWindowId?: string;
|
|
1096
|
+
}
|
|
1097
|
+
/** 菜单项——壳侧已解析(显示文本铁律:label 已 t(),池哑渲染)。titlebar 下拉与 ☰ 汉堡共用。 */
|
|
1098
|
+
export interface PoolMenuItem {
|
|
1099
|
+
/** 显示标签——壳 t(label ?? command.title ?? command) */
|
|
1100
|
+
label: string;
|
|
1101
|
+
/** 点击执行的命令 ID——无 command 父项为 ""(汉堡不展平父项,点击 no-op) */
|
|
1102
|
+
command: string;
|
|
1103
|
+
/** 快捷键显示文本——formatKeyLabel 后。仅汉堡(showKeybindings);titlebar 下拉无快捷键(同壳行为) */
|
|
1104
|
+
shortcut?: string;
|
|
1105
|
+
/** E5.8#148:当前项 √(显隐勾选菜单)——壳 buildTitleBarMenuGroups/汉堡经 resolveVisibilityChecked
|
|
1106
|
+
* 序列化(zone 可见 = ✓)。显示文本铁律:池哑渲染原文,壳只推布尔。 */
|
|
1107
|
+
checked?: boolean;
|
|
1108
|
+
/** 子菜单——titlebar 仅 command+children 父项携带(无 command 父项由壳展平);汉堡不展平 */
|
|
1109
|
+
children?: PoolMenuItem[];
|
|
1110
|
+
}
|
|
1111
|
+
/** 菜单组——titlebar 每个 group = 顶栏一个按钮(如"文件""查看");汉堡 = 分组区块 */
|
|
1112
|
+
export interface PoolMenuGroup {
|
|
1113
|
+
/** group 名——排序/定位键 */
|
|
1114
|
+
group: string;
|
|
1115
|
+
/** 组显示标签——壳 t(首项 label ?? group) */
|
|
1116
|
+
label: string;
|
|
1117
|
+
items: PoolMenuItem[];
|
|
1118
|
+
}
|
|
1119
|
+
/** 标题栏槽位按钮——插件 contributes.titleBar 声明(when 已由壳过滤) */
|
|
1120
|
+
export interface TitleBarSlotButton {
|
|
1121
|
+
command: string;
|
|
1122
|
+
/** codicon 类名或图片路径 */
|
|
1123
|
+
icon?: string;
|
|
1124
|
+
/** tooltip——与壳 TitleBar title={item.command} 行为一致 */
|
|
1125
|
+
title: string;
|
|
1126
|
+
}
|
|
1127
|
+
/** 标题栏布局——Phase 2 #5 TitleBarZone 消费 */
|
|
1128
|
+
export interface TitleBarLayout {
|
|
1129
|
+
title: string;
|
|
1130
|
+
/** Logo 资源 URL——壳 getAssetPath 解析(Path B:池不 import core) */
|
|
1131
|
+
logoUrl: string;
|
|
1132
|
+
menuBarVisible: boolean;
|
|
1133
|
+
/** 菜单栏数据——壳分组/展平/翻译后推送 */
|
|
1134
|
+
menuGroups: PoolMenuGroup[];
|
|
1135
|
+
/** 插件贡献槽位按钮(left/right) */
|
|
1136
|
+
slots: {
|
|
1137
|
+
left: TitleBarSlotButton[];
|
|
1138
|
+
right: TitleBarSlotButton[];
|
|
1139
|
+
};
|
|
1140
|
+
/** 窗口控件 tooltip——显示文本铁律:壳 t() 解析后推送(E5.8#46.18:pin/unpin 置顶两态) */
|
|
1141
|
+
windowControls: {
|
|
1142
|
+
minimize: string;
|
|
1143
|
+
maximize: string;
|
|
1144
|
+
restore: string;
|
|
1145
|
+
close: string;
|
|
1146
|
+
pin: string;
|
|
1147
|
+
unpin: string;
|
|
1148
|
+
};
|
|
1149
|
+
}
|
|
1150
|
+
/** 图标栏图标——壳 resolvePluginIcon 序列化(池不 import pluginLoader,Lucide 名由池映射组件渲染) */
|
|
1151
|
+
export type IconBarIcon = {
|
|
1152
|
+
kind: "lucide";
|
|
1153
|
+
name: string;
|
|
1154
|
+
} // E5#100 Lucide 优先
|
|
1155
|
+
| {
|
|
1156
|
+
kind: "codicon";
|
|
1157
|
+
name: string;
|
|
1158
|
+
} // codicon CSS 类
|
|
1159
|
+
| {
|
|
1160
|
+
kind: "img";
|
|
1161
|
+
src: string;
|
|
1162
|
+
} // linkdesk:// 协议 URL
|
|
1163
|
+
| {
|
|
1164
|
+
kind: "emoji";
|
|
1165
|
+
text: string;
|
|
1166
|
+
}; // 回退 emoji
|
|
1167
|
+
|
|
1168
|
+
/** 图标栏条目——序列化自壳 viewRegistry(pluginId + 图标 + 名称 + 位置) */
|
|
1169
|
+
export interface IconBarItem {
|
|
1170
|
+
pluginId: string;
|
|
1171
|
+
icon: IconBarIcon;
|
|
1172
|
+
/** tooltip / aria-label——壳 t(manifest.name) */
|
|
1173
|
+
label: string;
|
|
1174
|
+
/** 图标位置——getIconLocation:顶部活动图标 / 底部齿轮 */
|
|
1175
|
+
location: "top" | "bottom";
|
|
1176
|
+
}
|
|
1177
|
+
/** 图标栏布局——Phase 2 #6 IconBarZone 消费 */
|
|
1178
|
+
export interface IconBarLayout {
|
|
1179
|
+
icons: IconBarItem[];
|
|
1180
|
+
/** 激活图标——当前侧栏容器所属插件(侧栏折叠/无容器时不亮,壳 isActive 同款双重守卫) */
|
|
1181
|
+
activePluginId?: string;
|
|
1182
|
+
/** E3f #52h:☰ 汉堡可见——menuStyle hamburger/both */
|
|
1183
|
+
hamburgerVisible: boolean;
|
|
1184
|
+
/** 导航 aria-label——壳 t("导航")(显示文本铁律) */
|
|
1185
|
+
navLabel: string;
|
|
1186
|
+
/** ☰ 下拉——壳 MenuRenderer showGroups+showKeybindings+checkWhen 语义(不展平父项),仅 hamburgerVisible 时推 */
|
|
1187
|
+
hamburger?: {
|
|
1188
|
+
/** ☰ tooltip——壳 t("菜单") */
|
|
1189
|
+
title: string;
|
|
1190
|
+
groups: PoolMenuGroup[];
|
|
1191
|
+
};
|
|
1192
|
+
}
|
|
1193
|
+
/** 动作区下拉条目——label 显示文本(i18n key),command 执行,args 作为单个位置参数透传 */
|
|
1194
|
+
export interface TitleActionItem {
|
|
1195
|
+
/** 显示文本——i18n key(中文原文;池 t() 解析——显示文本铁律) */
|
|
1196
|
+
label: string;
|
|
1197
|
+
/** 点击执行的命令 ID */
|
|
1198
|
+
command: string;
|
|
1199
|
+
/** 命令参数——executeCommand(command, args) 单个位置参数透传(JSON 可序列化,无则省略) */
|
|
1200
|
+
args?: unknown;
|
|
1201
|
+
}
|
|
1202
|
+
/** 动作区 widget——三形态:icon 按钮 / 下拉菜单 / 主按钮+下拉复合(VS Code 终端 [+] + [▾] 同款)。
|
|
1203
|
+
* widget 是通用件不是给终端造的——谁声明谁用(通用 API 壳先行建设不等消费方,插件独立铁律)。 */
|
|
1204
|
+
export type TitleActionWidget =
|
|
1205
|
+
/** 单图标按钮——点击执行 command */
|
|
1206
|
+
{
|
|
1207
|
+
type: "icon";
|
|
1208
|
+
id: string;
|
|
1209
|
+
command: string;
|
|
1210
|
+
/** codicon 类名(如 "codicon-add")——池渲染 `<span className={`codicon ${icon}`} />` */
|
|
1211
|
+
icon: string;
|
|
1212
|
+
/** tooltip / aria-label——i18n key */
|
|
1213
|
+
title: string;
|
|
1214
|
+
args?: unknown;
|
|
1215
|
+
}
|
|
1216
|
+
/** 纯下拉——chevron 按钮展开 items 列表 */
|
|
1217
|
+
| {
|
|
1218
|
+
type: "dropdown";
|
|
1219
|
+
id: string;
|
|
1220
|
+
items: TitleActionItem[];
|
|
1221
|
+
/** chevron tooltip——i18n key */
|
|
1222
|
+
title?: string;
|
|
1223
|
+
}
|
|
1224
|
+
/** 主按钮+下拉复合——主按钮执行 command(默认动作),右侧 chevron 展开 items 备选 */
|
|
1225
|
+
| {
|
|
1226
|
+
type: "split";
|
|
1227
|
+
id: string;
|
|
1228
|
+
command: string;
|
|
1229
|
+
/** 主按钮图标——无 icon 时用 title(t() 后)作文本按钮 */
|
|
1230
|
+
icon?: string;
|
|
1231
|
+
/** 主按钮 tooltip / aria-label / 无 icon 时的文本——i18n key */
|
|
1232
|
+
title: string;
|
|
1233
|
+
items: TitleActionItem[];
|
|
1234
|
+
args?: unknown;
|
|
1235
|
+
};
|
|
1236
|
+
/** 侧栏 view 元数据——从 ViewContainerService 序列化,经 PoolLayout 推送到 SidebarPool */
|
|
1237
|
+
export interface SidebarViewMeta {
|
|
1238
|
+
id: string; // view ID("folders" / "search" / "installed")
|
|
1239
|
+
title: string; // 显示标题
|
|
1240
|
+
pluginId: string; // _pluginId——PluginComponent 用它找 import.meta.glob
|
|
1241
|
+
renderPath: string; // loader.ts 构建的 glob key——池 O(1) 查找 view 组件
|
|
1242
|
+
role?: "toolbar" | "section"; // 默认 "section"
|
|
1243
|
+
order?: number;
|
|
1244
|
+
collapsed?: boolean; // 插件声明的初始折叠态(collapsed: true)
|
|
1245
|
+
badge?: string | number;
|
|
1246
|
+
titleDescription?: string;
|
|
1247
|
+
titleTooltip?: string;
|
|
1248
|
+
singleViewPaneContainerTitle?: string; // mergeHeaderWhenSingle 时替代 containerTitle
|
|
1249
|
+
minHeight?: number; // 声明最小高度——PaneSash effectiveMinHeight
|
|
1250
|
+
/** E5.8#36.6:视图动作区声明透传——侧栏 section header 右侧(#36.5 同一声明,两处消费) */
|
|
1251
|
+
titleActions?: TitleActionWidget[];
|
|
1252
|
+
}
|
|
1253
|
+
/** E5.7#84:单个侧栏容器的池渲染数据——SidebarLayout.containers[] 元素(keep-alive 容器清单) */
|
|
1254
|
+
export interface SidebarContainerLayout {
|
|
1255
|
+
containerId: string;
|
|
1256
|
+
containerTitle: string;
|
|
1257
|
+
mergeHeaderWhenSingle?: boolean;
|
|
1258
|
+
views: SidebarViewMeta[];
|
|
1259
|
+
}
|
|
1260
|
+
/** 侧栏布局——仅 SidebarPool 接收 */
|
|
1261
|
+
export interface SidebarLayout {
|
|
1262
|
+
visible: boolean;
|
|
1263
|
+
width: number;
|
|
1264
|
+
/** 🆕 E5.8#36.8:侧栏所在边——#37.6 dockTo("sidebar", ...) 消费方(swap 规则:与 rightSidebar 恒占对边)。
|
|
1265
|
+
* 池 grid(#37.5)据此决定 sidebar 落左槽还是右槽。缺省 "left"。 */
|
|
1266
|
+
edge?: "left" | "right";
|
|
1267
|
+
// ── E5.6#11a:容器元数据 ──
|
|
1268
|
+
containerId: string | null; // "file-explorer" / "marketplace" / "serial-monitor"
|
|
1269
|
+
containerTitle: string; // "资源管理器" / "插件市场" / "串口监视器"
|
|
1270
|
+
mergeHeaderWhenSingle?: boolean;
|
|
1271
|
+
views: SidebarViewMeta[];
|
|
1272
|
+
/** E5.7#84:keep-alive 容器清单——全部侧栏容器(非仅活动)序列化。
|
|
1273
|
+
* 池按 containerId 常驻挂载、display:none 切换——切容器不卸载视图,插件组件状态不丢。
|
|
1274
|
+
* 容器随插件卸载从清单消失 → 池自然卸载(真相源在壳,池零缓存)。旧布局(无此字段)回退单容器渲染。 */
|
|
1275
|
+
containers?: SidebarContainerLayout[];
|
|
1276
|
+
collapsedViews?: string[]; // 持久化折叠的 view ID 集合——壳 loadCollapsedState()
|
|
1277
|
+
/** E5.6#11-fix7:壳通知池侧栏是否折叠——折叠=真消失(#147/#159 无窄条/▶,grid auto 列 0 宽) */
|
|
1278
|
+
collapsed?: boolean;
|
|
1279
|
+
// ── E5.7#10:侧栏 UI 文本壳侧 t() 推送(显示文本铁律——池渲染零自产文本) ──
|
|
1280
|
+
emptyText?: string; // 空状态主文案——"此容器没有已注册的视图"
|
|
1281
|
+
emptyHint?: string; // 空状态提示——"安装插件以添加视图"
|
|
1282
|
+
// ── E5.7#13:拖拽钳制界——壳 LayoutEngine dock 声明推送(池本地钳制对齐壳 resizeZone,零硬编码) ──
|
|
1283
|
+
minWidth?: number; // 拖拽最小宽——壳 dock.minWidth(170)
|
|
1284
|
+
maxWidth?: number; // 拖拽最大宽——壳 dock.maxWidth(600)
|
|
1285
|
+
// ── 向后兼容 ──
|
|
1286
|
+
/** @deprecated 被 views[] 取代——保留给未迁移的代码 */
|
|
1287
|
+
viewId?: string | null;
|
|
1288
|
+
}
|
|
1289
|
+
/** 🆕 E5.8#36.8:右侧栏布局——右侧栏真 zone(决策 6,E5.8#36.7 addZone("rightSidebar") 消费方)。
|
|
1290
|
+
* 与 SidebarLayout 对齐(消费字段同集),但**不携带自身 edge**——swap 规则保证 sidebar ↔ rightSidebar
|
|
1291
|
+
* 恒占对边,右栏 edge = sidebar 对边(池 grid #37.5 推导,防两处字面量)。
|
|
1292
|
+
* E5.8#37.5 RightSidebarZone 真渲染:文案壳 t() 推送(显示文本铁律)。#159 无 ◀/▶ 折叠按钮——与左栏同款。 */
|
|
1293
|
+
export interface RightSidebarLayout {
|
|
1294
|
+
visible: boolean;
|
|
1295
|
+
width: number;
|
|
1296
|
+
// ── 容器元数据(与 SidebarLayout 同语义)──
|
|
1297
|
+
containerId: string | null;
|
|
1298
|
+
containerTitle: string;
|
|
1299
|
+
mergeHeaderWhenSingle?: boolean;
|
|
1300
|
+
views: SidebarViewMeta[];
|
|
1301
|
+
containers?: SidebarContainerLayout[];
|
|
1302
|
+
collapsedViews?: string[];
|
|
1303
|
+
/** 🆕 E5.8#36.8 + #37.5 + #159:右栏折叠态——宽度 ≤48 派生(池),折叠=整个 zone 消失(与左栏 #147 同源,
|
|
1304
|
+
* 无窄条/▶——折叠/展开仅走图标栏 toggle + 界面勾选菜单) */
|
|
1305
|
+
collapsed?: boolean;
|
|
1306
|
+
// ── 拖拽钳制界 + 空态文案(与 SidebarLayout 同语义)──
|
|
1307
|
+
minWidth?: number;
|
|
1308
|
+
maxWidth?: number;
|
|
1309
|
+
emptyText?: string;
|
|
1310
|
+
emptyHint?: string;
|
|
1311
|
+
}
|
|
1312
|
+
/** 标签页在池中的表示——壳 pushLayout 时序列化 */
|
|
1313
|
+
export interface PoolTab {
|
|
1314
|
+
id: string;
|
|
1315
|
+
pluginId: string;
|
|
1316
|
+
title: string;
|
|
1317
|
+
sourceId?: string;
|
|
1318
|
+
dirty?: boolean;
|
|
1319
|
+
// 🆕 E5.6#16.5:TabBar 渲染所需元数据
|
|
1320
|
+
/** 插件图标 URL——getAssetPath() 解析后的路径 */
|
|
1321
|
+
icon?: string;
|
|
1322
|
+
/** 固定标签页(对标 VS Code pinned tabs) */
|
|
1323
|
+
pinned?: boolean;
|
|
1324
|
+
/** 标签页关闭行为——from plugin.json tabBehavior.closeBehavior */
|
|
1325
|
+
closeBehavior?: "normal" | "confirm" | "blocked";
|
|
1326
|
+
/** 单例插件(settings/marketplace 等)——TabBar 不显示 [×] 关闭按钮 */
|
|
1327
|
+
singleton?: boolean;
|
|
1328
|
+
/** 壳内部视图(欢迎页/插件详情/输出面板)——MainPool 内容区不渲染 PluginComponent */
|
|
1329
|
+
shellRendered?: boolean;
|
|
1330
|
+
/** 壳内部视图类型——"welcome" | "plugin-detail" | "output",池侧路由到对应组件 */
|
|
1331
|
+
shellType?: string;
|
|
1332
|
+
/** plugin-detail 视图的目标插件 ID(哪个插件的详情页) */
|
|
1333
|
+
detailPluginId?: string;
|
|
1334
|
+
}
|
|
1335
|
+
/** 分屏组——每个 group 占一个 flex 区域,内含 N 个 keep-alive 标签页 */
|
|
1336
|
+
export interface PoolGroup {
|
|
1337
|
+
id: string;
|
|
1338
|
+
flex: number;
|
|
1339
|
+
activeTabId: string;
|
|
1340
|
+
tabs: PoolTab[];
|
|
1341
|
+
}
|
|
1342
|
+
/** 递归分裂树节点——要么是叶子(含一个 TabGroup),要么是分叉(含两个子树) */
|
|
1343
|
+
export type SplitNode = {
|
|
1344
|
+
type: "leaf";
|
|
1345
|
+
groupId: string;
|
|
1346
|
+
} | {
|
|
1347
|
+
type: "branch";
|
|
1348
|
+
direction: "horizontal" | "vertical";
|
|
1349
|
+
children: [
|
|
1350
|
+
SplitNode,
|
|
1351
|
+
SplitNode
|
|
1352
|
+
];
|
|
1353
|
+
sizes: [
|
|
1354
|
+
number,
|
|
1355
|
+
number
|
|
1356
|
+
]; // 百分比,如 [50, 50]
|
|
1357
|
+
};
|
|
1358
|
+
/** [+] 按钮可创建的视图类型——壳 pushLayout 时从 getTabCreatableViews() 动态计算 */
|
|
1359
|
+
export interface CreatableViewMeta {
|
|
1360
|
+
pluginId: string;
|
|
1361
|
+
label: string;
|
|
1362
|
+
}
|
|
1363
|
+
/** 底部面板 view 元数据——面板视图注册序列化 */
|
|
1364
|
+
export interface PanelViewMeta {
|
|
1365
|
+
id: string;
|
|
1366
|
+
title: string;
|
|
1367
|
+
pluginId: string;
|
|
1368
|
+
/** E5.7#63.7:视图渲染入口路径——loader 解析(_renderPath),池 PluginComponent 动态 import。
|
|
1369
|
+
* ShellViewMeta 同款(sidebar 贡献),面板视图零特殊通道。 */
|
|
1370
|
+
renderPath: string;
|
|
1371
|
+
/** E5.8#36.5:视图动作区声明透传——PanelZone 标签栏右侧按活动视图渲染(无声明 → 右侧空白) */
|
|
1372
|
+
titleActions?: TitleActionWidget[];
|
|
1373
|
+
}
|
|
1374
|
+
/** E5.8#34:容器切换器下拉 item——含隐藏视图 + 显隐/激活标记(mockup 帧 2 拍板) */
|
|
1375
|
+
export interface PanelSwitcherItem {
|
|
1376
|
+
viewId: string;
|
|
1377
|
+
/** 视图名——壳 t() 已解析(显示文本铁律) */
|
|
1378
|
+
title: string;
|
|
1379
|
+
/** 所属插件 ID——sub 标签(如 "panel-demo") */
|
|
1380
|
+
pluginId: string;
|
|
1381
|
+
/** 当前可见性——✓ 勾选 = 可见 */
|
|
1382
|
+
visible: boolean;
|
|
1383
|
+
/** 是否激活视图 */
|
|
1384
|
+
active: boolean;
|
|
1385
|
+
}
|
|
1386
|
+
/** E5.8#34:容器切换器下拉分组——dd-group 容器标题 + dd-item 列表 */
|
|
1387
|
+
export interface PanelSwitcherGroup {
|
|
1388
|
+
containerId: string;
|
|
1389
|
+
/** 容器标题——壳 t() 已解析 */
|
|
1390
|
+
containerTitle: string;
|
|
1391
|
+
items: PanelSwitcherItem[];
|
|
1392
|
+
}
|
|
1393
|
+
/** 底部面板布局——Phase 5 #21 PanelZone 消费 */
|
|
1394
|
+
export interface PanelLayout {
|
|
1395
|
+
visible: boolean;
|
|
1396
|
+
height: number;
|
|
1397
|
+
/** 🆕 E5.8#36.8:面板 dock 边——#37.7 dockTo 消费方(面板位置)。顶/底=横带(align 控列跨度);
|
|
1398
|
+
* 左/右=主区与对应侧栏间竖条(5 带排布)。缺省 "bottom"。 */
|
|
1399
|
+
edge?: "bottom" | "top" | "left" | "right";
|
|
1400
|
+
/** 🆕 E5.8#36.8:面板横向对齐——#37.7 setAlign 消费方。几何由池 grid 推导(#37.5),壳只推配置。
|
|
1401
|
+
* center=主栏宽 / left=延伸到左侧栏之下 / right=延伸到右侧栏之下 / justify=全宽。缺省 "center"。 */
|
|
1402
|
+
align?: "left" | "center" | "right" | "justify";
|
|
1403
|
+
/** 🆕 E5.8#36.8:面板宽——edge∈{left,right} 时使用(竖条宽);顶/底仍用 height。缺省 300。 */
|
|
1404
|
+
width?: number;
|
|
1405
|
+
activeViewId: string;
|
|
1406
|
+
views: PanelViewMeta[];
|
|
1407
|
+
// ── E5.7#21 + #37.5:拖拽钳制界——#13 同款(壳 LayoutEngine dock 声明推送,池零硬编码)。
|
|
1408
|
+
// 轴感知:横带(edge∈{bottom,top})用 minHeight/maxHeight;竖条(edge∈{left,right})用 minWidth/maxWidth。 ──
|
|
1409
|
+
minHeight?: number;
|
|
1410
|
+
maxHeight?: number;
|
|
1411
|
+
/** 🆕 E5.8#37.5:竖条面板(左/右)拖拽最小/最大宽——壳 dock.minWidth/maxWidth 推送 */
|
|
1412
|
+
minWidth?: number;
|
|
1413
|
+
maxWidth?: number;
|
|
1414
|
+
/** E5.7#63.7:[+] 按钮 tooltip——壳 t("新建面板视图") 推送(显示文本铁律;壳无 panel:createView 监听 = 安全 no-op) */
|
|
1415
|
+
createTooltip?: string;
|
|
1416
|
+
/** E5.8#34:容器切换器下拉 DTO——按容器分组列全部视图(含隐藏),mockup 帧 2 */
|
|
1417
|
+
switcher?: PanelSwitcherGroup[];
|
|
1418
|
+
/** E5.8#34:空态占位主文本——全隐藏 / 无贡献视图时壳 t() 推送 */
|
|
1419
|
+
emptyText?: string;
|
|
1420
|
+
/** E5.8#34:空态占位指路——同 emptyText 壳 t() 推送 */
|
|
1421
|
+
emptyHint?: string;
|
|
1422
|
+
/** 🆕 E5.8#45:面板可脱出(PanelZone ⤢ 按钮显隐)——true 时渲染脱出按钮,点击 emit "panel:detach"(壳 detachPanel 接)
|
|
1423
|
+
* ——脱出后漂移面板窗独占渲染本面板(主区空占位 I9-13),drift 窗内置 false(面板已在外,无需再脱出) */
|
|
1424
|
+
detachable?: boolean;
|
|
1425
|
+
/** 🆕 E5.8#45:⤢ 按钮 tooltip——壳 t("面板独立窗口") 推送(显示文本铁律) */
|
|
1426
|
+
detachTooltip?: string;
|
|
1427
|
+
}
|
|
1428
|
+
/** 状态栏条目——序列化自壳 StatusBar 三源(贡献/动态/事件)+ 壳固定项(显示文本铁律:壳 t() 已解析)。
|
|
1429
|
+
* E5.8#20-c:改名 PoolStatusBarItem——与 api/types.ts StatusBarItem(manifest 贡献型)同名,
|
|
1430
|
+
* 契约平铺进单文件会声明合并成幽灵复合型(pluginId 变必选);池线用 Pool 前缀消歧。 */
|
|
1431
|
+
export interface PoolStatusBarItem {
|
|
1432
|
+
id: string;
|
|
1433
|
+
pluginId: string;
|
|
1434
|
+
/** codicon 图标名(不带 codicon- 前缀——池补) */
|
|
1435
|
+
icon?: string;
|
|
1436
|
+
label: string;
|
|
1437
|
+
title?: string;
|
|
1438
|
+
align: "left" | "right";
|
|
1439
|
+
/** 点击执行的命令 ID */
|
|
1440
|
+
onClick?: string;
|
|
1441
|
+
/** 插件有 statusBarComponent——池侧懒加载渲染(serial-monitor TX/RX 实时计数) */
|
|
1442
|
+
component?: boolean;
|
|
1443
|
+
/** 前导分隔线——壳 StatusBar 渲染语义(左区每项除首个;右区组内除首个) */
|
|
1444
|
+
dividerBefore?: boolean;
|
|
1445
|
+
}
|
|
1446
|
+
/** 通知动作——壳 ToastAction 序列化(onClick 是壳侧闭包——池点击回传壳执行) */
|
|
1447
|
+
export interface NotifAction {
|
|
1448
|
+
label: string;
|
|
1449
|
+
isPrimary?: boolean;
|
|
1450
|
+
}
|
|
1451
|
+
/** 通知条目——壳侧已解析(icon 类/时间/来源标签/动作全部壳侧完成) */
|
|
1452
|
+
export interface NotifItem {
|
|
1453
|
+
id: string;
|
|
1454
|
+
/** 完整 codicon 类串(如 "codicon codicon-error notif-severity-error") */
|
|
1455
|
+
iconClass: string;
|
|
1456
|
+
message: string;
|
|
1457
|
+
/** 壳 formatTimeAgo(i18n t()) */
|
|
1458
|
+
timeLabel: string;
|
|
1459
|
+
/** 壳 t("来源: {{source}}")——无 source 则缺省 */
|
|
1460
|
+
sourceLabel?: string;
|
|
1461
|
+
actions: NotifAction[];
|
|
1462
|
+
}
|
|
1463
|
+
/** 通知分组——壳 NotificationCenter buildSourceGroups(source 第一段归类 + 未读排序) */
|
|
1464
|
+
export interface NotifGroup {
|
|
1465
|
+
key: string;
|
|
1466
|
+
/** source 第一段或 t("其他") */
|
|
1467
|
+
label: string;
|
|
1468
|
+
unread: number;
|
|
1469
|
+
items: NotifItem[];
|
|
1470
|
+
}
|
|
1471
|
+
/** 通知中心数据——壳侧序列化(未读计数/文案/分组全壳侧完成) */
|
|
1472
|
+
export interface NotifLayout {
|
|
1473
|
+
unread: number;
|
|
1474
|
+
/** 铃铛 tooltip——t("{{count}} 条通知") / t("通知") */
|
|
1475
|
+
bellTitle: string;
|
|
1476
|
+
panelTitle: string;
|
|
1477
|
+
clearLabel: string;
|
|
1478
|
+
emptyLabel: string;
|
|
1479
|
+
dismissTitle: string;
|
|
1480
|
+
groups: NotifGroup[];
|
|
1481
|
+
}
|
|
1482
|
+
/** 状态栏布局——Phase 2 #8 StatusBarZone 消费 */
|
|
1483
|
+
export interface StatusBarLayout {
|
|
1484
|
+
items: PoolStatusBarItem[];
|
|
1485
|
+
/** Chord 提示——壳 CHORD_CHANGED 构建的完整字符串(按键名是技术标识符,不走 i18n) */
|
|
1486
|
+
chordLabel?: string;
|
|
1487
|
+
/** 通知中心——壳 toast 存储序列化(面板开闭/清除/动作回传壳执行) */
|
|
1488
|
+
notif: NotifLayout;
|
|
1489
|
+
}
|
|
1490
|
+
/**
|
|
1491
|
+
* PoolLayout v2——E5.7 唯一的 Pool 收到全量布局快照。
|
|
1492
|
+
* titleBar 必有(窗口 chrome——池恒渲染);iconBar/sidebar/statusBar/panel/rightSidebar 可选——
|
|
1493
|
+
* 主池恒推全量,脱出窗(E5.8#43-2 窗口模式策略表)只推 titleBar+groups 子集(池按字段条件渲染,无空列/空条)。
|
|
1494
|
+
*/
|
|
1495
|
+
export interface PoolLayout {
|
|
1496
|
+
version: 2;
|
|
1497
|
+
titleBar: TitleBarLayout;
|
|
1498
|
+
/** 图标栏——缺省 = 池不渲染该 zone(脱出窗子集;主池恒推) */
|
|
1499
|
+
iconBar?: IconBarLayout;
|
|
1500
|
+
/** 侧栏——缺省 = 池不渲染该 zone(脱出窗子集;主池恒推) */
|
|
1501
|
+
sidebar?: SidebarLayout;
|
|
1502
|
+
/** E5.8#36.8:右侧栏真 zone 布局——RightSidebarLayout(edge 反推 = sidebar 对边,不携带自身 edge) */
|
|
1503
|
+
rightSidebar?: RightSidebarLayout;
|
|
1504
|
+
groups: PoolGroup[];
|
|
1505
|
+
/** E5.8#30.15(P5):聚焦面板 id——点面板空白/点标签设置(壳 reduceFocusGroup/FocusTab)。
|
|
1506
|
+
* 池侧消费:accent 聚焦环 + isActive 单聚焦判定(tab.id === activeTabId && group.id === activeGroupId)。 */
|
|
1507
|
+
activeGroupId?: string;
|
|
1508
|
+
/** E5.6#16.7:递归分屏树——MainRenderer 递归渲染,替代平铺 groups.map。
|
|
1509
|
+
* leaf = 单 GroupPane,branch = 水平/垂直 flex 容器。 */
|
|
1510
|
+
root?: SplitNode;
|
|
1511
|
+
/** E5.6#16.7k-3:可创建为标签页的视图列表——池 GroupTabBar [+] 按钮动态菜单。
|
|
1512
|
+
* 空数组 = [+] 不提供创建菜单(脱出窗 I9-6);缺省 = 池兜底欢迎页 */
|
|
1513
|
+
creatableViews?: CreatableViewMeta[];
|
|
1514
|
+
panel?: PanelLayout;
|
|
1515
|
+
/** 状态栏——缺省 = 池不渲染该 zone(脱出窗子集;主池恒推) */
|
|
1516
|
+
statusBar?: StatusBarLayout;
|
|
1517
|
+
}
|
|
1518
|
+
/**
|
|
1519
|
+
* 池→壳侧栏动作 wire 契约——E5.7#97。
|
|
1520
|
+
*
|
|
1521
|
+
* 原定义在 PoolSectionStack.tsx(池组件内部类型),但走 IPC pool.sidebarAction 到壳
|
|
1522
|
+
* (preload-shell → usePoolSync → ViewContainerService)——跨堆协议,归口本目录。
|
|
1523
|
+
*/
|
|
1524
|
+
export interface SidebarAction {
|
|
1525
|
+
action: "reorder" | "setCollapsed" | "setVisible" | "toggleSidebarCollapse" | "setSidebarWidth";
|
|
1526
|
+
containerId?: string;
|
|
1527
|
+
viewId?: string;
|
|
1528
|
+
/** E5.8#41.9.2:setCollapsed 复合键持久化——池侧 view 自带 pluginId(SidebarViewMeta),壳侧精确寻址同名视图 */
|
|
1529
|
+
pluginId?: string;
|
|
1530
|
+
newIndex?: number;
|
|
1531
|
+
collapsed?: boolean;
|
|
1532
|
+
visible?: boolean;
|
|
1533
|
+
/** E5.7#13:分隔线拖拽 commit——resizeZone("sidebar", width)。E5.7#97 补入(原契约漏此变体) */
|
|
1534
|
+
width?: number;
|
|
1535
|
+
}
|
|
1536
|
+
/** 分屏方向——池侧 onDropSplit 已从 drop zone 归一化(MainZone:382) */
|
|
1537
|
+
export type TabSplitDirection = "horizontal" | "vertical";
|
|
1538
|
+
/**
|
|
1539
|
+
* 标签页拖拽分屏——类型 + drop zone 检测算法。
|
|
1540
|
+
* 设计依据:[V3-Phase3-标签页分屏设计.md §9]
|
|
1541
|
+
*/
|
|
1542
|
+
export type DropZone = "left" | "right" | "up" | "down" | "center" | null;
|
|
1543
|
+
/** 池→壳 tab 动作——union literal 即 wire 枚举 */
|
|
1544
|
+
export type PoolTabAction = {
|
|
1545
|
+
action: "focusTab";
|
|
1546
|
+
tabId: string;
|
|
1547
|
+
}
|
|
1548
|
+
// E5.8#30.15(P5):点击面板空白聚焦该面板——只改 activeGroupId 不改 activeTabId
|
|
1549
|
+
//(activeTabId 已是该组活跃标签;焦点=用户在看哪个面板,命令路由/聚焦环依赖它)
|
|
1550
|
+
| {
|
|
1551
|
+
action: "focusGroup";
|
|
1552
|
+
groupId: string;
|
|
1553
|
+
} | {
|
|
1554
|
+
action: "closeTab";
|
|
1555
|
+
tabId: string;
|
|
1556
|
+
}
|
|
1557
|
+
// closeOtherTabs/closeTabsToRight/closeAllTabs/duplicateTab 树内零发送方——
|
|
1558
|
+
// 但 tabAction 是插件可见 API(第三方插件可发),壳 switch 保留为契约面
|
|
1559
|
+
| {
|
|
1560
|
+
action: "closeOtherTabs";
|
|
1561
|
+
groupId: string;
|
|
1562
|
+
tabId: string;
|
|
1563
|
+
} | {
|
|
1564
|
+
action: "closeTabsToRight";
|
|
1565
|
+
groupId: string;
|
|
1566
|
+
tabId: string;
|
|
1567
|
+
} | {
|
|
1568
|
+
action: "closeAllTabs";
|
|
1569
|
+
groupId: string;
|
|
1570
|
+
} | {
|
|
1571
|
+
action: "reorderTab";
|
|
1572
|
+
groupId: string;
|
|
1573
|
+
tabId: string;
|
|
1574
|
+
newIndex: number;
|
|
1575
|
+
oldIndex: number;
|
|
1576
|
+
}
|
|
1577
|
+
// E5.8#51:newIndex = 目标组内插入缝(跨组拖拽落点 = 竖杠缝隙;缺省 append 末尾)
|
|
1578
|
+
| {
|
|
1579
|
+
action: "moveTab";
|
|
1580
|
+
tabId: string;
|
|
1581
|
+
targetGroupId: string;
|
|
1582
|
+
newIndex?: number;
|
|
1583
|
+
} | {
|
|
1584
|
+
action: "splitTab";
|
|
1585
|
+
tabId: string;
|
|
1586
|
+
direction: TabSplitDirection;
|
|
1587
|
+
zone?: DropZone;
|
|
1588
|
+
targetGroupId?: string;
|
|
1589
|
+
} | {
|
|
1590
|
+
action: "duplicateTab";
|
|
1591
|
+
tabId: string;
|
|
1592
|
+
} | {
|
|
1593
|
+
action: "pinTab";
|
|
1594
|
+
tabId: string;
|
|
1595
|
+
} | {
|
|
1596
|
+
action: "createTab";
|
|
1597
|
+
pluginId?: string;
|
|
1598
|
+
workspaceName?: string;
|
|
1599
|
+
} | {
|
|
1600
|
+
action: "updateSplitSizes";
|
|
1601
|
+
anchorGroupId: string;
|
|
1602
|
+
sizes: [
|
|
1603
|
+
number,
|
|
1604
|
+
number
|
|
1605
|
+
];
|
|
1606
|
+
branchIndex?: number;
|
|
1607
|
+
}
|
|
1608
|
+
// E5.8#44-B:标签页拖出窗口后释放——screenX/Y = 释放点屏幕坐标(壳侧命中检测:TabBar→并窗 / 空白→新窗)
|
|
1609
|
+
| {
|
|
1610
|
+
action: "releaseOutsideWindow";
|
|
1611
|
+
tabId: string;
|
|
1612
|
+
screenX: number;
|
|
1613
|
+
screenY: number;
|
|
1614
|
+
};
|
|
1615
|
+
/**
|
|
1616
|
+
* E5.8#43-4 ① 同款:壳侧接收的 tab 动作——主进程按 sender 解析注入 sourceWindowId(#44-B 权威窗口身份)。
|
|
1617
|
+
* 池永远不知自身 windowId;壳读 sourceWindowId 判源窗(detach 源 / 同窗不并)。
|
|
1618
|
+
*/
|
|
1619
|
+
export type ShellTabAction = PoolTabAction & {
|
|
1620
|
+
sourceWindowId: string;
|
|
1621
|
+
};
|
|
1622
|
+
/** E5.8#44-B:TabBar viewport rect——池侧 getBoundingClientRect 上报(吸附/释放并窗命中检测数据源)。
|
|
1623
|
+
* 坐标 = 视口相对(0,0 = 窗口内容区左上),壳持权威 window bounds 后转 screen(bounds.x + rect.left)。
|
|
1624
|
+
* groupId 携带——命中后 mergeTabToWindow 直落目标组。 */
|
|
1625
|
+
export interface TabBarViewportRect {
|
|
1626
|
+
groupId: string;
|
|
1627
|
+
left: number;
|
|
1628
|
+
top: number;
|
|
1629
|
+
width: number;
|
|
1630
|
+
height: number;
|
|
1631
|
+
}
|
|
1632
|
+
/** 池→壳:TabBar rects 上报载荷——主进程按 sender 解析附上 windowId(E5.8#44-B) */
|
|
1633
|
+
export interface TabBarRectsPayload {
|
|
1634
|
+
windowId: string;
|
|
1635
|
+
rects: TabBarViewportRect[];
|
|
1636
|
+
}
|
|
1637
|
+
/** E5.8#44-C:拖拽位置上报载荷——池拖出手势(拎起后 mousemove 全程)上报,壳排除源窗转 screen 吸附命中检测。
|
|
1638
|
+
* 坐标 = 屏幕坐标(e.screenX/screenY——窗口 bounds 同为屏幕坐标,可直接命中)。canceled = Esc 取消(keydown 无坐标)。 */
|
|
1639
|
+
export interface TabDragPositionPayload {
|
|
1640
|
+
tabId: string;
|
|
1641
|
+
screenX: number;
|
|
1642
|
+
screenY: number;
|
|
1643
|
+
/** Esc 取消拖拽——壳清吸附提示(keydown 无坐标,仅置标志;screenX/screenY 填 0) */
|
|
1644
|
+
canceled?: boolean;
|
|
1645
|
+
/** E5.8#46.19:被拖标签标题——池上报供主进程幽灵窗渲染文字(主进程不持 tabState,标题由池带)。壳/吸附忽略此字段 */
|
|
1646
|
+
title?: string;
|
|
1647
|
+
/** E5.8#46.19:光标是否在源窗外(屏坐标对照 winScreenX+视口尺寸,与 onMouseUp 窗外判定同源)——
|
|
1648
|
+
* 窗外 → 主进程 OS 幽灵显示(DOM 浮块出窗被裁剪);窗内 → OS 幽灵隐藏(DOM 浮块可见)。壳/吸附忽略此字段 */
|
|
1649
|
+
outside?: boolean;
|
|
1650
|
+
/** E5.8#46.19 进化:拖拽幽灵外观——主题三色(源池 getComputedStyle 读 --bg-card/--border/--text-primary,
|
|
1651
|
+
* 均为纯 hex 值)+ 被拖标签图标(tab.icon:emoji 字符或 getAssetPath 解析的图片 URL,iconKind 区分渲染)。
|
|
1652
|
+
* 仅 outside=true(窗外)时主进程消费;壳/吸附忽略此字段。可选用——旧池不带上限。
|
|
1653
|
+
* iconKind 判定与 DragOverlays 浮块同款(emoji:len≤2 且命中 emoji 正则;img:其余一律当图片 URL)。 */
|
|
1654
|
+
ghost?: {
|
|
1655
|
+
theme: {
|
|
1656
|
+
bg: string;
|
|
1657
|
+
border: string;
|
|
1658
|
+
text: string;
|
|
1659
|
+
};
|
|
1660
|
+
icon: string | null;
|
|
1661
|
+
iconKind: "emoji" | "img" | null;
|
|
1662
|
+
};
|
|
1663
|
+
}
|
|
1664
|
+
/** 池→壳:拖拽位置上报载荷——主进程按 sender 解析附上 sourceWindowId(E5.8#44-C 源窗排除——池永远不知自身 windowId) */
|
|
1665
|
+
export type ShellTabDragPosition = TabDragPositionPayload & {
|
|
1666
|
+
sourceWindowId: string;
|
|
1667
|
+
};
|
|
1668
|
+
/** 壳→池:吸附提示载荷——目标窗 TabBar 插入指示(groupId 命中)/ 清除(groupId null = 无吸附目标,清光)。
|
|
1669
|
+
* E5.8#46.10:groupId 命中时携带 viewportX/Y——光标在目标窗 viewport 坐标(壳由屏坐标 − 窗口 bounds 原点换算),
|
|
1670
|
+
* 目标池用它算插入缝隙(竖线落点,复用 computeTabInsertIndex)。 */
|
|
1671
|
+
export interface AdsorbHintPayload {
|
|
1672
|
+
groupId: string | null;
|
|
1673
|
+
viewportX?: number;
|
|
1674
|
+
viewportY?: number;
|
|
1675
|
+
}
|
|
1676
|
+
/** 池→壳:吸附插入缝隙回传——目标池每次算出新的缝隙(竖线落点)就上报,壳存吸附注册表供释放并窗精确落位。
|
|
1677
|
+
* windowId 由主进程按 sender 注入(池永远不知自身 windowId,E5.8#44 定案)。 */
|
|
1678
|
+
export interface AdsorbIndexPayload {
|
|
1679
|
+
windowId: string;
|
|
1680
|
+
groupId: string;
|
|
1681
|
+
/** 插入缝隙 0..tabs.length(竖线落点)——松手 merge 落位 = 竖线指的那根缝(提示不撒谎) */
|
|
1682
|
+
insertIndex: number;
|
|
1683
|
+
}
|
|
1684
|
+
/** QuickPick 动作——select/highlight/close/itemAction 按 key 回传 */
|
|
1685
|
+
export interface PoolQuickPickAction {
|
|
1686
|
+
type: string;
|
|
1687
|
+
key?: string;
|
|
1688
|
+
actionId?: string;
|
|
1689
|
+
}
|
|
1690
|
+
/** Toast 动作——dismiss/action 按 id + actionId 回传 */
|
|
1691
|
+
export interface PoolToastAction {
|
|
1692
|
+
type: string;
|
|
1693
|
+
id: string;
|
|
1694
|
+
actionId?: string;
|
|
1695
|
+
}
|
|
1696
|
+
/** Dialog 动作——confirm/cancel 回传,壳侧 settle Promise */
|
|
1697
|
+
export interface PoolDialogAction {
|
|
1698
|
+
type: string;
|
|
1699
|
+
}
|
|
1700
|
+
/** 悬浮面板动作——action 按 actionId 回传(open-in/close),壳侧 settle Promise(E5.8#37 类型 B) */
|
|
1701
|
+
export interface PoolFloatingPanelAction {
|
|
1702
|
+
type: string;
|
|
1703
|
+
actionId?: string;
|
|
1704
|
+
}
|
|
1705
|
+
/** 内存压力通知——主进程 window-manager 采样超阈值(E5.7#39) */
|
|
1706
|
+
export interface MemoryPressureData {
|
|
1707
|
+
totalRSS: number;
|
|
1708
|
+
threshold: number;
|
|
1709
|
+
}
|
|
1710
|
+
/** 壳→主:创建池窗请求——windowId 壳生成(tabState 归属),bounds 可选(E5.8#43-1 A4 多窗口底座) */
|
|
1711
|
+
export interface CreatePoolWindowRequest {
|
|
1712
|
+
windowId: string;
|
|
1713
|
+
width?: number;
|
|
1714
|
+
height?: number;
|
|
1715
|
+
x?: number;
|
|
1716
|
+
y?: number;
|
|
1717
|
+
}
|
|
1718
|
+
/** E5.8#43-3:池窗位置/大小变更矩形——主进程 moved/resized 事件上报(壳据 windowId 更新注册表 + 落盘 A6)。
|
|
1719
|
+
* 非独立契约入口(契约生成器 walkRefs 命中引用即强制 export 进 linkdesk.d.ts)——源码不 export,knip 不报死面。 */
|
|
1720
|
+
export interface WindowBounds {
|
|
1721
|
+
x: number;
|
|
1722
|
+
y: number;
|
|
1723
|
+
width: number;
|
|
1724
|
+
height: number;
|
|
1725
|
+
}
|
|
1726
|
+
/** 主→壳:脱出池窗 bounds 变更通知(用户移动/缩放窗口)——壳持久化浮窗位置(I9-14 位置/大小记录) */
|
|
1727
|
+
export interface PoolWindowBoundsPayload {
|
|
1728
|
+
windowId: string;
|
|
1729
|
+
bounds: WindowBounds;
|
|
1730
|
+
}
|
|
1731
|
+
/** 壳↔插件中继/池控制/窗口/壳级命令/热退出暂存命名空间面——双端注入面(bridge 真壳独有 / hotExit 池侧独有) */
|
|
1732
|
+
export interface ShellAPI {
|
|
1733
|
+
/** 壳↔插件通信中继——壳 preload 独有 */
|
|
1734
|
+
bridge?: {
|
|
1735
|
+
onRequest(cb: (req: BridgeRequestPayload) => void): () => void;
|
|
1736
|
+
respond(requestId: string, result?: unknown, error?: string): void;
|
|
1737
|
+
broadcast(channel: string, payload: unknown): void;
|
|
1738
|
+
notifyConfigChanged(key: string, value: unknown): void;
|
|
1739
|
+
};
|
|
1740
|
+
/** 池控制——壳 preload:推送布局 + 注册池→壳动作回调;池 preload:收布局 + 发动作。双端各实现自己那半(方法级子集面,surfaces.ts) */
|
|
1741
|
+
pool: {
|
|
1742
|
+
// ── 壳侧(池 preload 无) ──
|
|
1743
|
+
/** E5.8#43-2:windowId 可选定向推送(缺省 'main')——壳窗口注册表遍历按 id 推送各窗布局 */
|
|
1744
|
+
pushLayout(layout: PoolLayout, windowId?: string): void;
|
|
1745
|
+
/** E5.8#43-1 A3:回调收 windowId(主池='main',脱出池=壳生成 id)——壳据 id 定向推该窗布局 */
|
|
1746
|
+
onReady(cb: (windowId: string) => void): () => void;
|
|
1747
|
+
toggleDevTools(): void;
|
|
1748
|
+
onSidebarAction(cb: (action: SidebarAction) => void): () => void;
|
|
1749
|
+
// E5.8#44-B:壳侧收 action = ShellTabAction(主进程按 sender 注入 sourceWindowId——#43-4 权威窗口身份)
|
|
1750
|
+
onTabAction(cb: (action: ShellTabAction) => void): () => void;
|
|
1751
|
+
// E5.8#44-B:池→壳 TabBar viewport rects 上报(吸附/释放并窗命中检测数据源)——windowId 由主进程注入
|
|
1752
|
+
onTabBarRects(cb: (payload: TabBarRectsPayload) => void): () => void;
|
|
1753
|
+
// E5.8#44-C:池→壳 拖拽位置上报(拎起后 mousemove 全程)——sourceWindowId 由主进程注入(壳排除源窗命中)
|
|
1754
|
+
onDragPosition(cb: (pos: ShellTabDragPosition) => void): () => void;
|
|
1755
|
+
// E5.8#44-C:壳→池 吸附提示(目标窗 TabBar 插入指示/清除)——windowId 壳命中解析后定向推送(#46.10 载荷带 viewport 坐标)
|
|
1756
|
+
pushAdsorbHint(hint: AdsorbHintPayload, windowId: string): void;
|
|
1757
|
+
// E5.8#46.10:池→壳 吸附插入缝隙回传(壳侧——windowId 由主进程注入,壳存吸附注册表供释放并窗精确落位)
|
|
1758
|
+
onAdsorbIndex(cb: (payload: AdsorbIndexPayload) => void): () => void;
|
|
1759
|
+
pushQuickPick(data: unknown): void;
|
|
1760
|
+
onQuickPickAction(cb: (action: PoolQuickPickAction) => void): () => void;
|
|
1761
|
+
pushToast(data: unknown): void;
|
|
1762
|
+
onToastAction(cb: (action: PoolToastAction) => void): () => void;
|
|
1763
|
+
pushDialog(data: unknown): void;
|
|
1764
|
+
onDialogAction(cb: (action: PoolDialogAction) => void): () => void;
|
|
1765
|
+
// E5.8#37(Phase 8 类型 B):壳内悬浮面板——pushPanel 哑渲染数据 + 动作回传
|
|
1766
|
+
pushFloatingPanel(data: unknown): void;
|
|
1767
|
+
onFloatingPanelAction(cb: (action: PoolFloatingPanelAction) => void): () => void;
|
|
1768
|
+
onMemoryPressure(cb: (data: MemoryPressureData) => void): () => void;
|
|
1769
|
+
// ── E5.8#43-1(A4):多窗口底座——壳驱动创建/关闭池窗 + 监听 OS 关窗(主进程执行窗口生命周期)──
|
|
1770
|
+
createWindow(opts: CreatePoolWindowRequest): void;
|
|
1771
|
+
closeWindow(windowId: string): void;
|
|
1772
|
+
onWindowClosed(cb: (windowId: string) => void): () => void;
|
|
1773
|
+
// ── E5.8#43-3:主→壳 池窗 bounds 变更(moved/resized 上报)——壳注册表更新 + 落盘浮窗位置(I9-14)──
|
|
1774
|
+
onWindowBoundsChanged(cb: (payload: PoolWindowBoundsPayload) => void): () => void;
|
|
1775
|
+
// ── 池侧(壳 preload 无) ──
|
|
1776
|
+
onLayout(cb: (layout: PoolLayout) => void): () => void;
|
|
1777
|
+
ready(): void;
|
|
1778
|
+
sidebarAction(action: SidebarAction): void;
|
|
1779
|
+
tabAction(action: PoolTabAction): void;
|
|
1780
|
+
// E5.8#44-B:池→壳 TabBar viewport rects 上报(池侧——MainZone useTabDrag 报告 getBoundingClientRect)
|
|
1781
|
+
tabBarRects(rects: TabBarViewportRect[]): void;
|
|
1782
|
+
// E5.8#44-C:池→壳 拖拽位置上报(池侧——useDragReorder 拎起后 mousemove 上报,壳吸附命中)
|
|
1783
|
+
dragPosition(pos: TabDragPositionPayload): void;
|
|
1784
|
+
// E5.8#44-C:壳→池 吸附提示订阅(池侧——MainZone 订阅目标窗 TabBar 插入指示/清除)
|
|
1785
|
+
onAdsorbHint(cb: (hint: AdsorbHintPayload) => void): () => void;
|
|
1786
|
+
// E5.8#46.10:池→壳 吸附插入缝隙回传(池侧——目标池算竖线落点后上报,壳释放并窗精确落位)
|
|
1787
|
+
adsorbIndex(payload: {
|
|
1788
|
+
groupId: string;
|
|
1789
|
+
insertIndex: number;
|
|
1790
|
+
}): void;
|
|
1791
|
+
// ── E5.8#30.16(P8):通用「beforeClose 可取消」通道(池侧)──
|
|
1792
|
+
// 插件注册 handler(自己定逻辑:弹确认/清理资源/返回 boolean 决定是否允许关标签页);
|
|
1793
|
+
// GroupTabBar 关闭路径 `await beforeClose`——handler 返回 false(或 Promise<false>)则关闭被取消。
|
|
1794
|
+
registerBeforeClose(pluginId: string, handler: (tab: PoolTab) => boolean | Promise<boolean>): void;
|
|
1795
|
+
unregisterBeforeClose(pluginId: string): void;
|
|
1796
|
+
beforeClose(pluginId: string, tab: PoolTab): Promise<boolean>;
|
|
1797
|
+
};
|
|
1798
|
+
/** 窗口控制——TitleBar 按钮映射,双端注入(11 方法同通道,共享模块 electron/window-namespace.ts) */
|
|
1799
|
+
window: {
|
|
1800
|
+
minimize(): void;
|
|
1801
|
+
maximize(): void;
|
|
1802
|
+
unmaximize(): void;
|
|
1803
|
+
close(): void;
|
|
1804
|
+
/** E5.7#79:缩放因子 → 主进程 setZoomFactor(池 WCV) */
|
|
1805
|
+
setZoom(factor: number): void;
|
|
1806
|
+
toggleDevTools(): Promise<void>;
|
|
1807
|
+
isMaximized(): Promise<boolean>;
|
|
1808
|
+
onMaximizeChange(cb: (maximized: boolean) => void): () => void;
|
|
1809
|
+
/** E5.8#46.18:OS 级置顶(盖过其他应用)——true 置顶 / false 解除;按 sender 路由宿主窗 */
|
|
1810
|
+
setAlwaysOnTop(pinned: boolean): void;
|
|
1811
|
+
isAlwaysOnTop(): Promise<boolean>;
|
|
1812
|
+
onAlwaysOnTopChange(cb: (pinned: boolean) => void): () => void;
|
|
1813
|
+
};
|
|
1814
|
+
/** 壳级命令——revealInOS / openInTerminal / startDrag,双端注入 */
|
|
1815
|
+
shell: {
|
|
1816
|
+
showItemInFolder(p: string): Promise<void>;
|
|
1817
|
+
openInTerminal(dirPath: string, terminalExe?: string, customCommand?: string): Promise<void>;
|
|
1818
|
+
startDrag(filePath: string, iconPath?: string): void;
|
|
1819
|
+
};
|
|
1820
|
+
/** 热退出暂存——编辑器未保存内容落盘(E5.7#53)。`?`:池侧独有(壳 preload 不注入) */
|
|
1821
|
+
hotExit?: {
|
|
1822
|
+
save(filePath: string, content: string): Promise<void>;
|
|
1823
|
+
load(filePath: string): Promise<string | null>;
|
|
1824
|
+
clear(filePath: string): Promise<void>;
|
|
1825
|
+
};
|
|
1826
|
+
/** OS 拖入文件路径获取——双端注入 */
|
|
1827
|
+
getFilePath: (file: File) => string;
|
|
1828
|
+
}
|
|
1829
|
+
/** 底部面板命名空间面——对标 VS Code vscode.window.createTreeView 后 focus / 视图提升语义 */
|
|
1830
|
+
export interface PanelAPI {
|
|
1831
|
+
panel: {
|
|
1832
|
+
/** 聚焦底部面板视图——面板隐藏则展开并切到该视图;已显示则切换聚焦。viewId 不在 panel 容器时 no-op */
|
|
1833
|
+
reveal(viewId: string): Promise<void>;
|
|
1834
|
+
/** 壳内悬浮面板(类型 B)——按声明弹出某视图(I8-2 身份开关键)。viewId 未声明视图时 no-op。
|
|
1835
|
+
* E5.8#41.18:可选 pluginId 复合寻址——两插件同名 viewId(双设置套并存)时插件侧携带
|
|
1836
|
+
* pluginId 精确命中目标套(壳侧路径 Ctrl+,/右键已带;裸 viewId 多命中 fail-loud no-op) */
|
|
1837
|
+
revealFloating(viewId: string, pluginId?: string): Promise<void>;
|
|
1838
|
+
};
|
|
1839
|
+
}
|
|
1840
|
+
/** 设置套条目——settings.list() 返回的一行。
|
|
1841
|
+
* 非导出(模块内接口)——契约生成器经 SettingsAPI.list 传递引用自动收集并 emit export;
|
|
1842
|
+
* 壳内无第三方消费方,导出会被 knip 报未用(linkdesk-api.ts 排除域不算消费)。 */
|
|
1843
|
+
export interface SettingsPluginInfo {
|
|
1844
|
+
/** 插件 ID——getActive/setActive 的句柄 */
|
|
1845
|
+
pluginId: string;
|
|
1846
|
+
/** 插件显示名(manifest.name 原文,消费方自做 i18n) */
|
|
1847
|
+
title: string;
|
|
1848
|
+
}
|
|
1849
|
+
/** 设置套命名空间面——双端注入(设置 UI 在池内渲染,壳侧实现走 IPC 桥) */
|
|
1850
|
+
export interface SettingsAPI {
|
|
1851
|
+
settings: {
|
|
1852
|
+
/** 全部声明 factoryRole:"settings" 的设置套(含默认/内置),注册序 */
|
|
1853
|
+
list(): Promise<SettingsPluginInfo[]>;
|
|
1854
|
+
/** 当前活动设置套 ID——读持久化激活(#41.12 落盘),无记录/已卸载回退默认(内置) */
|
|
1855
|
+
getActive(): Promise<string | undefined>;
|
|
1856
|
+
/** 切换活动设置套——校验候选后落盘持久化(重启保持)。非候选 fail-loud 抛错 */
|
|
1857
|
+
setActive(pluginId: string): Promise<void>;
|
|
1858
|
+
};
|
|
1859
|
+
}
|
|
1860
|
+
/** 插槽条目——factorySlots.list(role) 返回的一行。
|
|
1861
|
+
* 非导出(模块内接口)——契约生成器经 list 传递引用自动收集并 emit export;
|
|
1862
|
+
* 壳内无第三方消费方,导出会被 knip 报未用(linkdesk-api.ts 排除域不算消费)。 */
|
|
1863
|
+
export interface FactorySlotEntry {
|
|
1864
|
+
/** 插件 ID——getActive/setActive 的句柄 */
|
|
1865
|
+
pluginId: string;
|
|
1866
|
+
/** 插件显示名(manifest.name 原文,消费方自做 i18n) */
|
|
1867
|
+
title: string;
|
|
1868
|
+
/** E5.8#41.18:该插件 contributes.floatingPanel.viewId(无声明 = undefined)——切换/打开候选悬浮面板用 */
|
|
1869
|
+
viewId?: string;
|
|
1870
|
+
}
|
|
1871
|
+
/** factorySlots 命名空间面——双端注入(池内渲染侧实现走 IPC 桥) */
|
|
1872
|
+
export interface FactorySlotsAPI {
|
|
1873
|
+
factorySlots: {
|
|
1874
|
+
/** 全部已填充角色的名字(注册序)——设置页「任何 factoryRole ≥2 候选 → 该角色名组出现」先枚举角色再 list(role) 判候选数 */
|
|
1875
|
+
listRoles(): Promise<string[]>;
|
|
1876
|
+
/** 全部声明指定 factoryRole 的候选插件 [{pluginId, title}],注册序 */
|
|
1877
|
+
list(role: string): Promise<FactorySlotEntry[]>;
|
|
1878
|
+
/** 指定角色的活动插件 ID——读持久化激活(#41.12 落盘),无记录/已卸载回退默认(内置) */
|
|
1879
|
+
getActive(role: string): Promise<string | undefined>;
|
|
1880
|
+
/** 切换指定角色活动插件——校验候选后落盘持久化(重启保持)。非候选 fail-loud 抛错 */
|
|
1881
|
+
setActive(role: string, pluginId: string): Promise<void>;
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1884
|
+
/**
|
|
1885
|
+
* linkdesk API——插件代码的类型安全入口。
|
|
1886
|
+
* 对标 VS Code `vscode` 对象的全局命名空间结构。
|
|
1887
|
+
* 池 preload 注入的命名空间为插件运行时真相源(required);
|
|
1888
|
+
* 仅 bridge(真壳独有)/ hotExit(池侧独有)为 `?` 可选——另一侧不注入(E5.8#22 审视 N1 修正:
|
|
1889
|
+
* 其余桥面 window/pool/shell/getFilePath 双端实有注入,契约标必选)。
|
|
1890
|
+
* E5.8#0d.10-9e:由 12 个命名空间域接口交叉组装(interface→type intersection,
|
|
1891
|
+
* 索引访问 LinkDeskAPI["pool"]/["configuration"] 等消费方契约不变)。
|
|
1892
|
+
*/
|
|
1893
|
+
export type LinkDeskAPI = CommandsAPI & AppearanceAPI & TabsAPI & KeybindingsAPI & UiAPI & DataAPI & WorkspaceAPI & EditorAPI & PluginsAPI & ShellAPI & PanelAPI & SettingsAPI & FactorySlotsAPI;
|
|
1894
|
+
/** 图标映射条目——字体 glyph 形态(单色/带色字体,seti 类每图标一色;codicon 即保底单色) */
|
|
1895
|
+
export interface IconThemeGlyph {
|
|
1896
|
+
/** CSS 类名(codicon 保底 / 自定义图标字体资产) */
|
|
1897
|
+
class: string;
|
|
1898
|
+
/** 可选每图标颜色(seti 类彩色字体) */
|
|
1899
|
+
color?: string;
|
|
1900
|
+
}
|
|
1901
|
+
/** 图标映射条目——图像资产形态(任意多色/拟物化/贴图) */
|
|
1902
|
+
export interface IconThemeImage {
|
|
1903
|
+
/** 图像资产相对路径——壳加载时解析为 linkdesk:// 绝对 URL(getPluginAssetPath),消费方零解析负担 */
|
|
1904
|
+
imagePath: string;
|
|
1905
|
+
}
|
|
1906
|
+
/** 图标映射条目——双形态(E5.8#133 ④ 拍板:字体 glyph 或图像资产,同一主题可混用,壳零审查) */
|
|
1907
|
+
export type IconThemeMapping = IconThemeGlyph | IconThemeImage;
|
|
1908
|
+
/** 图标主题映射表——fileExtensions/fileNames/folderNames → 双形态条目 */
|
|
1909
|
+
export interface IconThemeMappings {
|
|
1910
|
+
files?: Record<string, IconThemeMapping>;
|
|
1911
|
+
extensions?: Record<string, IconThemeMapping>;
|
|
1912
|
+
folders?: Record<string, IconThemeMapping>;
|
|
1913
|
+
/** 文件夹打开态——可选,未指定则复用 folders */
|
|
1914
|
+
foldersExpanded?: Record<string, IconThemeMapping>;
|
|
1915
|
+
/* ── 默认图标(E5.8#133.6:对齐 VS Code iconTheme 顶层默认键——未命中匹配表时用主题默认而非 codicon 保底) ── */
|
|
1916
|
+
/** 默认文件图标——未命中 files/extensions 时使用(缺省 = 壳 codicon 保底) */
|
|
1917
|
+
file?: IconThemeMapping;
|
|
1918
|
+
/** 默认文件夹图标——未命中 folders 时使用(缺省 = 壳 codicon 保底) */
|
|
1919
|
+
folder?: IconThemeMapping;
|
|
1920
|
+
/** 默认文件夹展开图标——未命中 foldersExpanded 时使用(缺省 = 壳 codicon 保底) */
|
|
1921
|
+
folderExpanded?: IconThemeMapping;
|
|
1922
|
+
/** 根文件夹图标(缺省 = 壳 codicon 保底) */
|
|
1923
|
+
rootFolder?: IconThemeMapping;
|
|
1924
|
+
/** 根文件夹展开图标(缺省 = 壳 codicon 保底) */
|
|
1925
|
+
rootFolderExpanded?: IconThemeMapping;
|
|
1926
|
+
}
|
|
1927
|
+
/** 插件状态变更——plugin-state:changed 载荷(跨 WebView 状态同步原语) */
|
|
1928
|
+
export interface PluginStateChangedPayload {
|
|
1929
|
+
pluginId: string;
|
|
1930
|
+
key: string;
|
|
1931
|
+
value: unknown;
|
|
1932
|
+
}
|
|
1933
|
+
|
|
1934
|
+
declare global {
|
|
1935
|
+
interface Window {
|
|
1936
|
+
/** 插件 API——对标 VS Code vscode 命名空间(由 preload-pool.ts / preload-shell.ts 注入) */
|
|
1937
|
+
linkdesk: LinkDeskAPI;
|
|
1938
|
+
}
|
|
1939
|
+
}
|
|
1940
|
+
|
|
1941
|
+
export {};
|