> ## Documentation Index
> Fetch the complete documentation index at: https://agent.minimaxi.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Client API 参考

> 页面侧 window.mcode.miniapp 的方法签名、参数、返回值、权限和生命周期。

本页介绍正式版已提供的宿主接口，并在对应章节注明版本差异。场景示例见[页面 Client API 指南](https://agent.minimaxi.com/docs/miniapp/authors/client-api.md)，版本支持见[能力与进展](https://agent.minimaxi.com/docs/miniapp/progress.md)。

## 入口与存在性

```typescript theme={null}
const miniapp = window.mcode?.miniapp;
```

宿主通过 preload 向受管理的 Mini App 主页面注入 `window.mcode`，不需要安装运行时 SDK，也不需要传插件 ID。普通浏览器、其他网页和较旧宿主可能没有这些对象，调用前先检查对象是否存在。

v3.1.6 的主页面会暴露下列命名空间；对象存在不代表 manifest 已声明能力或用户已开启权限。需要权限的调用由宿主核对页面身份、声明和对应开关。Node 使用另一套 [Node API](https://agent.minimaxi.com/docs/miniapp/reference/node-api.md)。

| 成员 | 页面入口 | 说明 |
| - | - | - |
| `message` | `miniapp.message.append` | 经确认追加到输入框草稿 |
| `window` | `miniapp.window` | 自己的窗口句柄，实验性 |
| `speech` | `miniapp.speech.transcribe` | 宿主语音转写 |
| `tool` | `miniapp.tool.request` | 提前请求工具授权；页面没有 `list` 或 `call` |
| `agent` | `miniapp.agent` | 页面侧 Agent API，见[完整参考](https://agent.minimaxi.com/docs/miniapp/reference/agent-api.md) |
| `capabilities` | `miniapp.capabilities.has` | 同步查询宿主接口支持 |

页面异步接口拒绝 Promise 时，会将小写错误码写入 `Error.message`；不要依赖 Node 风格的 `code`、`retryable` 或 `disposition`，见[页面错误约定](https://agent.minimaxi.com/docs/miniapp/reference/errors.md#client)。

## message.append

```typescript theme={null}
interface MiniAppMessageAPI {
  append(text: string): Promise<void>;
}
```

| 参数 | 类型 | 说明 |
| - | - | - |
| `text` | `string` | 纯文本，最多 100,000 个 UTF-16 码元；保留空格、制表符和换行，HTML 也按文字处理 |

每次调用都会弹出宿主确认框，不支持「记住选择」。空字符串也需要确认，但不改变草稿。用户确认后，宿主保留输入框已有的文字、引用和附件，再追加新文字；Promise 完成只表示草稿已追加，不表示消息已发送或 Agent 已开始运行。

目标始终是页面所在的本地可写会话；目标不可用时，不会改投其他会话、首页草稿或新建会话。此接口不授予会话读取能力，也不能修改已发送的消息。没有页面侧取消参数；用户可在确认框拒绝。`result_unknown` 表示结果未确认，应先查看输入框再决定是否重试。

错误为 `user_cancelled`、`invalid_request`、`text_too_large`、`not_allowed`、`target_unavailable`、`result_unknown`，见[错误码](https://agent.minimaxi.com/docs/miniapp/reference/errors.md#client)。

## window

窗口句柄接口仍可能调整，使用前先做特性检测。它只控制调用页面自己的窗口。`id` 是不透明的稳定字符串，不是会话 ID，也不是运行 ID；页面弹出或回到文件面板时不改变。

```typescript theme={null}
interface MiniAppWindowHandle {
  readonly id: string;
  getState(): Promise<MiniAppWindowState>;
  update(patch: MiniAppWindowPatch): Promise<MiniAppWindowState>;
  focus(): Promise<void>;
  onDidChangeState(
    listener: (state: MiniAppWindowState) => void,
  ): { dispose(): void };
}

type MiniAppWindowState =
  | { readonly mode: 'inline'; readonly modeChangeReloadsPage?: boolean }
  | {
      readonly mode: 'window';
      readonly window: MiniAppWindowOptions;
      readonly modeChangeReloadsPage?: boolean;
    };
```

### 状态字段

`getState()` 无参数。`inline` 表示页面在文件面板中，没有 `window` 字段；`window` 表示独立窗口，并返回以下全部字段。

两种状态都可能在顶层返回 `modeChangeReloadsPage`，说明切换模式是否会重建页面，见[页面重建与确认](#window-reload)。

| `window` 字段 | 类型 | 含义 |
| - | - | - |
| `width` / `height` | `number` | 内容区宽高，与更新时使用的尺寸一致 |
| `minWidth` / `minHeight` | `number` | manifest 的最小尺寸；未声明时分别为 480、360 |
| `x` / `y` | `number` | 内容区在屏幕中的坐标，不是外边框坐标 |
| `visible` | `boolean` | 窗口是否可见 |
| `resizable` | `boolean` | 当前窗口是否允许调整尺寸 |
| `frame` | `boolean` | 是否有系统边框 |
| `transparent` | `boolean` | 是否使用透明窗口 |
| `alwaysOnTop` | `boolean` | 是否置顶 |
| `clickThrough` | `boolean` | 是否让鼠标事件穿透 |
| `skipTaskbar` | `boolean` | 是否不在任务栏显示 |

### update(patch)

```typescript theme={null}
interface MiniAppWindowPatch {
  readonly mode?: 'inline' | 'window';
  readonly width?: number;
  readonly height?: number;
  readonly x?: number;
  readonly y?: number;
  readonly visible?: boolean;
  readonly resizable?: boolean;
  readonly alwaysOnTop?: boolean;
  readonly clickThrough?: boolean;
  readonly skipTaskbar?: boolean;
}
```

成功回复包含完整的 `MiniAppWindowState`。字段均可省略，省略或值为 `undefined` 的字段保持不变；空对象合法。未知字段、错误类型或非有限数值返回 `invalid_request`。v3.1.10 中用户取消切窗确认时，调用成功返回当前状态，`mode` 仍为原值，不能把成功回复当作目标 `mode` 已生效，见[页面重建与确认](#window-reload)。

| 字段或操作 | 规则 |
| - | - |
| `mode` | 只能为 `inline` 或 `window`；即使目标模式相同，也必须在 `navigator.userActivation.isActive` 为 `true` 的用户手势中调用 |
| `width` / `height` | 有限数值，必须大于 0 且不超过 10,000；应用时取整并至少达到窗口最小尺寸。如果 manifest 声明或更新后的窗口不允许调整尺寸，通过程序调整尺寸也会被拒绝 |
| `x` / `y` | 有限数值，范围为 −100,000 到 100,000；应用时取整 |
| `alwaysOnTop: true` / `clickThrough: true` | manifest 的 `surface.window` 必须预先将对应项声明为 `true`；关闭这两项不需要该上限 |
| `visible` | 隐藏本身不关闭页面，脚本、计时器和网络请求继续运行；无用户手势时显示窗口不会主动抢焦点 |
| `frame`、`transparent`、`minWidth`、`minHeight` | 只能在 manifest 声明，运行时 patch 包含这些字段会返回 `not_permitted` |
| 内嵌状态 | 目标仍为 `inline` 时，patch 不能带 `mode` 之外的窗口属性，否则返回 `inline_mode` |

更新 `x`、`y`、`width` 或 `height` 时，宿主会检查取整并应用最小尺寸后的最终内容矩形：它与同一显示器工作区在横纵方向都必须至少重叠 40 px；不满足时返回 `not_permitted`。仅更新尺寸也会检查这条规则。

同一帧内不带 `mode` 的更新会合并，后写的字段覆盖先写的字段；该帧内的所有调用收到相同结果，或一同被拒绝。带 `mode` 的更新立即发出，避免等待下一帧时失去用户手势。

### focus()

无参数，返回 `Promise<void>`，必须在用户手势中调用。独立窗口会恢复最小化、显示并聚焦；内嵌页面会请求聚焦宿主并选中自己的标签，不应依赖它自动展开已折叠的文件面板。它不会创建新页面，也不允许控制其他 Mini App。

### onDidChangeState(listener)

同步返回 `{ dispose() }`。非函数监听器会同步抛出 `Error('invalid_request')`。当前文档仍存活且 `update()` 收到成功回复时，会通知监听器；这不保证 `mode` 已改变，应检查收到的状态。文档存活期间，拖动窗口等外部变化由周期检查发现，不保证每一个中间状态都会触发通知。首次订阅不立即发送初始状态，需要初始值时先调用 `getState()`。

调用 `dispose()` 结束订阅；页面离开时也会清理监听。监听器自身抛错不会中断窗口更新。窗口方法的错误为 `inline_mode`、`not_permitted`、`busy`、`result_unknown`、`invalid_request`；`result_unknown` 后用 `getState()` 核对状态，见[窗口错误](https://agent.minimaxi.com/docs/miniapp/reference/errors.md#window)。

### 页面重建与确认

v3.1.9 及以上正式版可在状态中返回 `modeChangeReloadsPage?: boolean`。这是可选字段，应按 `getState()` 的运行时结果判断，不能写进 `update` 的 patch。值为 `true` 时，实际切换 `inline` / `window` 模式会重建页面。使用原生页面移动方式的宿主不返回这个标志，不能把所有窗口切换都视为重载。

重建会保留逻辑窗口 ID 和 Node 服务，但当前文档、JavaScript 内存状态、媒体流、页面订阅和待完成的页面 Promise 不会延续。先保存必要状态，不要把必须执行的工作放在 `await update({ mode })` 后，也不要等待旧文档的 `onDidChangeState` 确认切换完成。目标文档启动后重新调用 `getState()`、恢复已保存的内容并重新订阅。未返回标志也不能保证页面不会因宿主刷新、崩溃等原因结束。

从 v3.1.10 起，需要重建页面的弹出和收回操作，会先在宿主主窗口中提示影响并等待用户确认。关闭独立窗口或按 Cmd/Ctrl+W 也走这条确认流程，等待期间不会先隐藏或销毁原窗口。用户取消时，页面和请求保持不变，原窗口继续保留；`update()` 成功返回当前状态，`mode` 可能仍是原值，不会以 `user_cancelled` 拒绝。用户确认后，旧页面的请求和订阅随页面结束而取消或清理；不会撤销已完成的操作，也不会自动重放请求。

## speech.transcribe

```typescript theme={null}
interface MiniAppSpeechAudioFormat {
  readonly sampleRate: 16000;
  readonly channelCount: 1;
  readonly sampleFormat: 's16';
}

interface MiniAppSpeechTranscribeInput {
  readonly audio: ArrayBuffer | ArrayBufferView;
  readonly format: MiniAppSpeechAudioFormat;
}

interface MiniAppSpeechTranscribeOptions {
  readonly onPartial?: (text: string) => void;
}

interface MiniAppSpeechAPI {
  transcribe(
    input: MiniAppSpeechTranscribeInput,
    options?: MiniAppSpeechTranscribeOptions,
  ): Promise<{ readonly text: string }>;
}
```

| 参数 | 说明 |
| - | - |
| `input.audio` | 一段原始 PCM，至少一个样本，字节数必须为偶数，最多 16,000,000 字节（500 秒）。可传 `Int16Array`、`ArrayBuffer` 或基于普通 `ArrayBuffer` 的 view；不接受共享缓冲区 |
| `input.format` | 必须只包含上述三个字段和值：16 kHz、单声道、有符号 16 位 little-endian PCM。其他采样率、声道或额外 format 字段均拒绝 |
| `options.onPartial` | 可选回调，接收宿主转写期间的阶段文本；最终文本以返回的 `text` 为准。回调抛错会记录到页面控制台，不中断转写 |

需声明 `deviceAccess: ["microphone"]` 并保持麦克风开关开启。页面负责采集音频、决定录音何时结束、转换样本并停止所有媒体 track；宿主收到完整录音后才转写，`onPartial` 不是边录边识别的实时字幕。不要直接传 WAV、WebM、Ogg、FLAC、MP3 或 `MediaRecorder` 产物。

同一 Mini App 同时只能有一个转写，另一次返回 `busy`。没有页面侧 `signal` 或 `cancel()` 参数；页面结束会中止在途转写，宿主处理时限为 180 秒。关闭麦克风开关会拒绝后续调用，不会强制停止页面已经持有的媒体流。

错误为 `invalid_request`、`not_permitted`、`audio_too_large`、`busy`、`runtime_unavailable`、`transcription_failed`、`result_unknown`，见[语音转写错误](https://agent.minimaxi.com/docs/miniapp/reference/errors.md#speech)。录音示例见[指南](https://agent.minimaxi.com/docs/miniapp/authors/client-api.md#speech)。

## tool.request

```typescript theme={null}
interface MiniAppToolRequestAPI {
  request(
    names: readonly string[],
  ): Promise<Record<string, 'allow' | 'ask' | 'deny'>>;
}
```

| 参数或返回值 | 说明 |
| - | - |
| `names` | 1–10 个互不重复、非空的运行时工具名，每项最多 1,024 个 UTF-8 字节。必须从 Node 的 `context.tool.list()` 获取，再通过业务接口传给页面，不要自行拼接 |
| 返回值 | 以请求的工具名为键的权限快照；`allow` 可调用，`ask` 仍需确认，`deny` 当前不允许。它不是后续调用的授权凭据 |

需声明 `toolAccess: ["call"]`，Node 服务必须正在运行，并且必须直接在用户手势中调用。宿主只询问当前仍为 `ask` 的工具，用户可勾选要「始终允许」的项；未勾选或拒绝不一定会让整个请求失败，应以返回的实际权限为准。已经 `allow` 或 `deny` 的项不会因本次请求改为其他状态。

用户关闭工具调用开关时，所有请求名称都返回 `deny`，不弹出确认框。未声明 `toolAccess` 时没有可用的工具会话；Node 工具会话或通道不可用时，调用以 `runtime_unavailable` 拒绝。页面没有工具的 `list()`、`call()`，也没有本方法的取消参数；实际调用位于 [Node tool API](https://agent.minimaxi.com/docs/miniapp/reference/node-api.md#tools)。后续每次调用仍由宿主重新判定权限。

错误为 `invalid_request`、`not_permitted`、`approval_required`、`runtime_unavailable`、`result_unknown`，见[工具授权错误](https://agent.minimaxi.com/docs/miniapp/reference/errors.md#tool-request)。页面只应读取拒绝的 `Error.message`，不能依赖 Node 端错误附带的 `permissions` 字段。

## capabilities.has

```typescript theme={null}
interface MiniAppHostCapabilities {
  has(name: string): boolean;
}
```

同步返回布尔值，不发起授权或宿主异步调用。未知名称返回 `false`；运行时传入非字符串也返回 `false`。旧宿主可能没有 `capabilities`，使用 `miniapp?.capabilities?.has(name)` 做检测。

下表列出 v3.1.6 的全部 14 个名称。表按宿主版本固定，页面和 Node 共用；`true` 只表示宿主实现了该能力，不保证当前端有对应对象，更不代表 manifest 声明或用户授权。

| 名称 | 页面入口（`miniapp.` 前缀） | Node 入口 |
| - | - | - |
| `agent.agents` | `agent.agents()` | `context.agent.agents()` |
| `agent.create` | `agent.create()` | `context.agent.create()` |
| `agent.models` | `agent.models()` | `context.agent.models()` |
| `agent.observe` | `agent.observe()` | `context.agent.observe()` |
| `agent.open` | `agent.open()` | 无 |
| `agent.run` | `agent.run()` | `context.agent.run()` |
| `agent.session` | `agent.session()` | `context.agent.session(id)` |
| `agent.sessions` | `agent.sessions()` | `context.agent.sessions()` |
| `hostConnector` | 无 | `context.hostConnector` |
| `message.append` | `message.append()` | 无 |
| `speech.transcribe` | `speech.transcribe()` | 无 |
| `tool` | 无列出或调用接口 | `context.tool` |
| `tool.request` | `tool.request()` | `context.tool.request()` |
| `window` | `window` 句柄 | 无 |

`agent.reply`、`agent.answer`、`agent.cancel` 不是独立能力名，不能用这些名称推断方法支持。仍需按对应 API 检查接口是否存在、权限是否满足。

## Agent 命名空间

`miniapp.agent` 的页面侧 `run`、`reply`、`answer`、`cancel`、`open`、目录查询和会话观察，及与 Node 的参数差异，统一见 [Agent API 参考](https://agent.minimaxi.com/docs/miniapp/reference/agent-api.md)。

## 摄像头与系统通知

这两项从 MiniMax Code v3.1.9 起正式支持，使用标准浏览器 API，不增加宿主命名空间或能力探测名称。使用前在 `engines.mcode` 中声明最低版本，并在 `deviceAccess` 中声明对应项；用户可在插件详情关闭权限。

| 声明项 | 页面操作 | 条件 |
| - | - | - |
| `camera` | `navigator.mediaDevices.getUserMedia({ video: true })` | 摄像头已声明且开关开启；操作系统也可能要求授权 |
| `notifications` | `new Notification(...)` | 通知已声明且开关开启；通知由创建它的页面处理 |

同时请求音视频时，`microphone` 和 `camera` 两项都必须声明并开启。用户关闭权限后，新采集请求会被拒绝；页面已经取得的媒体流仍需自行停止。标准采集错误（例如 `NotAllowedError`）由浏览器 API 抛出，不采用宿主语音转写错误码。

通知点击回调可在原页面仍存活时调用窗口句柄的 `focus()`，不应依赖它展开已折叠的文件面板。原页面关闭或重载后，旧通知不能重新打开页面；这里不提供页面关闭后的后台通知能力。

示例与使用限制见[摄像头](https://agent.minimaxi.com/docs/miniapp/authors/client-api.md#camera)和[系统通知](https://agent.minimaxi.com/docs/miniapp/authors/client-api.md#notifications)指南。
