协议扩展与生成契约补全规格
定义应用扩展清单、保留命名、生成契约、能力查询与重载恢复目标边界。
定义应用扩展清单、保留命名、配置校验、生成契约、能力查询和重载恢复的目标边界。
| 状态项 | 说明 |
|---|---|
当前 26.11.5 | 当前 26.11.5 基线为 63 个命令、3 个事件、18 个插件、18 个权限、11 个错误码;Windows 62 个命令、Android 55 个命令,两端各 3 个事件。内置命令与事件由 protocol/commands.json 和 tools/codegen.py 固定生成,CLI 不接受顶层 extensions。 |
目标规格(未发布) | 规格 / 待实现:顶层 extensions 与扩展清单进入配置校验;KSM.configureExtensions(contract) 注册前端契约;扩展事件订阅在重载后恢复;插件上下文统一携带 windowId、事件发送器、取消令牌和大结果句柄写入器。 |
实施阶段 | P0;依赖 P1–P4 的应用扩展命令注册,依赖 P5 的包与发布。 |
验收标准 | pnpm validate:protocol、pnpm codegen 后三端契约零漂移;非法命名、冲突、缺权限和跨平台声明被 CLI 拒绝;扩展命令不进入 protocol/commands.json。 |
本页只描述通用扩展声明与生成链路。内置命令、事件、权限、插件和错误码仍以 protocol/ 为唯一事实源。应用扩展命令与事件由应用清单声明,在宿主插件中注册,不复制框架生成契约,也不承载业务数据模型。
| 层级 | 真实入口 | 加载顺序 |
|---|---|---|
| 配置 schema | protocol/kasumi.config.schema.json | 先声明顶层 extensions 字段结构。 |
| Node CLI | packages/kasumi-cli/src/config.mjs | 解析 kasumi.config.json 并校验扩展清单。 |
| Python CLI | cli/kasumi_config.py | 与 Node CLI 使用同一字段和错误语义。 |
| 模板与诊断 | packages/create-kasumi/templates/、pnpm ksm doctor | 生成最小配置,对缺清单和冲突给出可操作提示,不改写用户文件。 |
| 生成契约 | tools/codegen.py、tools/validate_protocol.py | 生成内置三端契约;扩展契约分别位于 .ksm/dev/extension-contract.json 与 .ksm/dist/extension-contract.json。 |
| 前端 | frontend/src/bridge/ksm.ts、frontend/src/index.ts、frontend/src/generated/contract.ts | 初始化传输,加载扩展契约,恢复能力与事件订阅。 |
| 宿主 | windows/src/plugins/ksm_plugin.h、android/kasumi/src/main/java/dev/kasumi/app/bridge/KSMPlugin.kt、KSMRouter.kt | 按 windowId 注册插件、发送事件并检查权限。 |
| 能力 | 当前 26.11.5 基线 | 目标规格 / 待实现 |
|---|---|---|
| 配置字段 | kasumi.config.json 只接受现有 windows、android、平台策略、权限与命令白名单。 | 顶层 extensions 数组,每项为 { id, manifest, platforms };manifest 为仓库内相对路径。 |
| 命令命名 | 只有生成命令;事件表固定为 webview.navigated、webview.reloaded、window.resized。 | 扩展命令使用 app.<domain>.<action>,扩展事件使用 app.<domain>.<event>;保留 core.*、ksm.* 和所有生成名。 |
| 参数校验 | validateKSMArgs 只覆盖生成命令。 | 扩展清单使用 JSON Schema 子集;前端守卫与双端路由器使用同一生成校验器。 |
| 事件订阅 | KSM.on()、KSM.subscribe()、KSM.unsubscribe() 只接受生成事件。 | 同一组入口接受扩展事件;webview.reloaded 后重新查询能力并恢复订阅。 |
| 插件上下文 | 当前插件上下文没有统一的事件发送器、取消令牌和大结果写入器。 | Windows 与 Android 的 KSMPluginContext 统一携带 windowId、订阅感知事件发送器、取消令牌和 { file } 写入器。 |
| 错误码 | 共享错误码为 11 类。 | 新增 EXTENSION_CONFLICT;其余复用现有错误码。 |
| 产物 | 生成契约只描述内置能力。 | 内置契约仍由 tools/codegen.py 生成;扩展契约由 CLI 生成到 .ksm/dev/ 与 .ksm/dist/。 |
| 保留项 | 规则 |
|---|---|
core.*、ksm.* | 框架保留,扩展清单不得使用。 |
| 生成命令与事件 | 来自 protocol/commands.json;扩展不得重名。 |
| 扩展 ID | 同一配置内唯一;重复返回 EXTENSION_CONFLICT。 |
| 平台声明 | 每个命令和事件显式列出 windows、android;未声明平台不得进入能力查询。 |
since | 只从 version.json 的版本元数据生成,不在配置、CLI 或文档中硬编码。 |
以下示例描述目标接口,尚未在 26.11.5 发布。kasumi.config.json 的顶层字段由 protocol/kasumi.config.schema.json、packages/kasumi-cli/src/config.mjs 和 cli/kasumi_config.py 共同校验:
{
"windows": {
"packageName": "dev.kasumi.example",
"version": "1.0.0",
"commands": "all"
},
"android": {
"packageName": "dev.kasumi.example",
"version": "1.0.0",
"commands": "all"
},
"extensions": [
{
"id": "library",
"manifest": "extensions/library.json",
"platforms": ["windows", "android"]
}
]
}清单使用中性名称,声明命令、事件、平台、权限及参数/结果的 JSON Schema 子集:
{
"id": "library",
"commands": [
{
"name": "app.library.scan.start",
"platforms": ["windows", "android"],
"permissions": ["fs.read", "media.probe"],
"args": {},
"result": {}
}
],
"events": [
{
"name": "app.library.scan.progress",
"platforms": ["windows", "android"],
"payload": {}
}
]
}扩展命令不进入 protocol/commands.json。CLI 把清单编译为扩展契约,KSM.configureExtensions(contract) 在初始化后、业务调用前加载:
import { KSM, KSMWebMessageTransport } from 'kasumi-bridge';
const extensionContract = await fetch('/.ksm/dev/extension-contract.json')
.then((response) => response.json());
KSM.initialize(new KSMWebMessageTransport());
KSM.configureExtensions(extensionContract);
const capabilities = await KSM.capabilities();
const permission = await KSM.permission.request('fs.read');
if (!permission.granted || !capabilities.commands.includes('app.library.scan.start')) {
throw new Error('The library extension is unavailable.');
}
const off = KSM.on<{ scanned: number }>(
'app.library.scan.progress',
(payload) => console.info(payload.scanned)
);
await KSM.subscribe('app.library.scan.progress');
await KSM.invoke('app.library.scan.start', {});
off();
await KSM.unsubscribe('app.library.scan.progress');大结果不进入消息体。扩展命令返回 { file: 'app://tmp/...' },前端用 KSM.fs.readText() 读取;事件载荷同样保持小对象。
| 平台 | 实现边界 | 行为 |
|---|---|---|
| Windows | windows/src/plugins/ksm_plugin.h、ksm_plugin_registry.cpp、windows/src/bridge/ksm_router.cpp | 插件注册表按 windowId 保存扩展命令、事件与校验器;KSMPluginContext 发送事件前检查订阅表和权限;窗口销毁时取消令牌并丢弃迟到响应。 |
| Android | android/kasumi/src/main/java/dev/kasumi/app/bridge/KSMPlugin.kt、KSMWebViewHost.kt、KSMRouter.kt | KSMWebViewHost 按 windowId 持有扩展订阅;close() 只注销当前窗口;onTrimMemory 不取消其他窗口任务;Activity 或 Application 管理共享 Host Services。 |
两端生成名仍来自 tools/codegen.py。扩展清单的 CLI 校验结果进入 capabilities.query,不把未注册平台列入能力集合。
app.library.scan.start 等业务扩展命令加入 protocol/commands.json;扩展清单属于应用配置,不属于内置协议。core.*、ksm.*、生成命令名或生成事件名作为扩展 ID、命令或事件;不重复声明同一扩展 ID。window.chrome.webview.postMessage()、Android JavaScript interface 或自行拼接响应;所有调用从 KSM 根入口进入。addJavascriptInterface,不向前端暴露真实路径,不在 JSON 中传递超过 64 KiB 的载荷,不引入 Rust/Node 中间 runtime,不写前端平台分支。.ksm/dev/ 缓存当作生产产物,不把未声明平台的命令列入 capabilities.query。webview.reloaded 后复用旧请求 ID 或旧订阅句柄;恢复流程必须重新查询能力并重新订阅。| 错误码 | 触发条件 | 期望行为 |
|---|---|---|
INVALID_ARGS | manifest 字段、Schema 子集、命令参数或事件载荷非法。 | CLI 或前端守卫在入口拒绝。 |
UNKNOWN_COMMAND | 扩展未注册、平台未声明或命令 allowlist 未启用。 | 路由器拒绝并记录命令名。 |
PERMISSION_DENIED | 扩展权限或运行时授权未通过。 | 原生层在插件执行前拒绝。 |
NOT_SUPPORTED | 当前宿主平台不在扩展平台矩阵中。 | 能力查询排除该命令或事件。 |
CANCELLED / TIMEOUT | 窗口销毁、重载或请求超时。 | 取消令牌传播,抑制迟到响应。 |
EXTENSION_CONFLICT | 扩展 ID、命令、事件与保留名或其他扩展冲突。 | CLI 配置阶段生成可定位的字段路径错误。 |
IO_ERROR | manifest 读取或扩展契约写入失败。 | 保留原产物,返回可操作诊断。 |
INTERNAL_ERROR | 生成契约与已注册插件不一致。 | 路由器拒绝启动并输出插件 ID。 |
| 现象 | 优先检查 |
|---|---|
app.* 命令返回 UNKNOWN_COMMAND | 扩展契约是否加载、命令是否在 allowlist、宿主插件是否注册到当前 windowId。 |
| 事件订阅失败 | 事件名是否在清单中、平台矩阵、订阅表、webview.reloaded 恢复流程。 |
| 重载后扩展失效 | KSM.capabilities() 缓存是否清理、扩展契约是否重新配置、订阅是否重新同步。 |
| CLI 生成契约漂移 | protocol/kasumi.config.schema.json、Node CLI、Python CLI、模板和 tools/codegen.py 输出。 |
| 两个窗口收到彼此事件 | windowId 隔离、事件发送器目标窗口、订阅表所有权。 |
扩展命令返回 { file } 后读取失败 | 虚拟路径是否在 app://tmp、句柄是否过期、消息大小是否超过 64 KiB。 |
pnpm validate:protocol 与 pnpm codegen 通过,生成差异只包含预期契约;git diff --check 无错误。pnpm ksm doctor 对缺 manifest、未知字段、重复 ID、保留名冲突、缺权限和跨平台未声明给出可操作提示,不自动改写用户文件。pnpm typecheck、pnpm test:contract、pnpm test:packages、pnpm test:tarballs 通过;干净目录初始化后可加载扩展契约。protocol/commands.json;capabilities.query、事件表、allowlist 和平台矩阵一致。{ file }、多窗口隔离和权限拒绝均有前端契约与双端平台测试。
评论