---
title: "Dialog"
description: "Kasumi 对话框插件的方法、权限、安全边界与平台差异。"
---


> 理解 Dialog 插件的系统消息框、确认框、文件选择和保存边界。

## 模块边界

Dialog 插件只显示原生用户交互并返回选择结果。它不读取、写入或删除文件，也不向前端暴露
真实宿主路径。文件选择结果必须继续交给 Filesystem 插件处理。

| 层级 | 入口 | 责任 |
| --- | --- | --- |
| 前端 API | `frontend/src/api/dialog.ts` | 参数守卫和命令封装 |
| 协议清单 | `protocol/plugins.json` | `dialog` 插件和四个命令归属 |
| Windows 插件 | `windows/src/plugins/ksm_dialog_plugin.cpp` | Win32 消息框和文件选择器 |
| Android 插件 | `KSMDialogPlugin.kt` | `AlertDialog` 与文档选择 Intent |

## 平台与权限

| 命令 | Windows | Android | 权限 | 返回 |
| --- | --- | --- | --- | --- |
| `dialog.message` | 支持 | 支持 | `dialog` | `{ confirmed }` |
| `dialog.confirm` | 支持 | 支持 | `dialog` | `{ confirmed }` |
| `dialog.openFile` | 支持 | 支持 | `dialog` | `{ file }` |
| `dialog.saveFile` | 支持 | 支持 | `dialog` | `{ file }` |

文件选择结果为空时返回 `{ file: null }`，不是 `CANCELLED`。消息框或确认框取消时返回
`{ confirmed: false }`。

## 方法与配置

| 方法 | 参数 | 说明 |
| --- | --- | --- |
| `message({ title, message })` | 两个非空字符串 | 显示单按钮消息 |
| `confirm({ title, message })` | 两个非空字符串 | 显示确认与取消选择 |
| `openFile({ filters? })` | 平台相关过滤数组 | 返回 picked 文件句柄 |
| `saveFile({ suggestedName? })` | 建议文件名 | 返回 picked 保存句柄 |

Windows `filters` 使用文件对话框过滤表达式；Android 把过滤项传给
`Intent.EXTRA_MIME_TYPES`。两端没有统一的扩展名语义，跨平台业务必须在应用层转换。

## 安全与生命周期

- 不返回真实宿主路径或 `content://` URI。
- Android 同一时间只接受一个文件打开或保存请求，其余请求返回 `BUSY`。
- Android 宿主内部等待上限是 60 秒，但前端默认请求超时是 10 秒。
- 用户停留超过请求超时后，Promise 先以 `TIMEOUT` 拒绝；宿主抑制迟到结果。
- 页面重载或 Activity 销毁时，当前窗口等待中的对话框请求必须被取消或丢弃。

## 示例

```ts
const confirmation = await KSM.dialog.confirm({
  title: '删除缓存',
  message: '确定删除全部缓存吗？'
});

if (!confirmation.confirmed) {
  return;
}

const picked = await KSM.dialog.openFile({
  filters: ['text/plain']
});

if (!picked.file) {
  return;
}

const text = await KSM.fs.readText({ path: picked.file });
console.info(text);
```

需要更长等待时间时，显式传入不超过 600000 毫秒的超时：

```ts
await KSM.invoke(
  'dialog.openFile',
  { filters: ['application/json'] },
  60000
);
```

## 平台差异

Windows 使用 `MessageBoxW`、`GetOpenFileNameW` 和 `GetSaveFileNameW`；Android 使用
`AlertDialog`、`ACTION_OPEN_DOCUMENT` 和 `ACTION_CREATE_DOCUMENT`。Android 的系统文档
选择器可能由其他应用提供，返回结果只通过 picked token 暴露。

## 错误行为

| 错误码 | 场景 |
| --- | --- |
| `INVALID_ARGS` | 标题、正文、过滤项或建议文件名非法 |
| `PERMISSION_DENIED` | 未授予 `dialog` 或当前窗口不允许文件选择 |
| `BUSY` | 已有打开或保存请求进行中 |
| `NOT_SUPPORTED` | 宿主未注册原生对话框服务 |
| `TIMEOUT` / `CANCELLED` | 请求超时或窗口销毁 |

## 排查路径

1. 确认 `capabilities.commands` 包含目标对话框命令。
2. 确认当前窗口拥有 `dialog` 权限。
3. Android `filters` 使用 MIME 类型，Windows 使用文件过滤表达式。
4. 用户长时间未操作时，提高显式超时或调整交互流程。
5. 返回 picked 句柄后不要拼接子路径或转换成本地路径。
6. 页面重载后重新发起请求，不复用旧对话框结果。
