# context.events

事件先在 [events](./events-manifest.md) 中声明。它适合报告“刷新完成”这类发生过的事情；需要持续读取当前值时，使用状态来源。

## emit()

把事件提交给宿主事件总线。

```ts
context.events.emit(eventId: string, payload: Record<string, unknown>): Promise<{ emitted: boolean }>
```

### 参数

| 名称 | 类型 | 说明 |
| --- | --- | --- |
| `eventId` | `string` | 清单中的事件 ID。 |
| `payload` | `Record<string, unknown>` | 符合事件 `payloadSchema` 的 JSON 对象。 |

### 返回值

Promise 解析为 `{ emitted: boolean }`。当前事件不保留快照，也不自动触发用户流程。

### 示例

```js
await context.events.emit("refreshed", { count: 3 });
```

## subscribe()

插件后台可订阅其他插件显式开放给 `plugins` 的事件。调用前，在清单顶层声明提供方依赖与事件接口版本：

```json
{
  "dependencies": { "builtin.window-automation": "^1.0.0" },
  "eventSubscriptions": [
    { "pluginId": "builtin.window-automation", "eventId": "foreground.changed", "version": 1 }
  ],
  "hostCapabilities": { "required": { "events.subscribe": 1 } }
}
```

```ts
context.events.subscribe<Payload>(
  pluginId: string,
  eventId: string,
  listener: (event: Readonly<PluginEvent<Payload>>) => void | Promise<void>
): Promise<() => Promise<void>>
```

宿主核对消费方身份、依赖包版本、事件版本、提供方运行与授权状态。订阅版本取自清单，调用方不能自行扩大访问范围。返回值是异步取消函数，可在 `onStop` 调用；宿主也会在消费方停止或崩溃时清理其订阅。

```js
let unsubscribe;
definePlugin({
  async onStart({ events }) {
    unsubscribe = await events.subscribe(
      'builtin.window-automation', 'foreground.changed', event => {
        console.log(event.payload.application?.appId);
      }
    );
  },
  async onStop() { await unsubscribe?.(); }
});
```

回调收到 `{pluginId,eventId,version,emittedAt,payload}`，身份和时间由宿主填写。事件不回放、不持久化，发布成功不表示消费方已处理。每个订阅的 SDK 队列最多 64 个等待事件，按接收顺序串行调用回调；每个消费进程的宿主传输最多 64 个或 256 KiB 在途事件。队列满时丢弃新事件，回调异常只记录诊断，不影响发布者和其他订阅。取消订阅不会中断已开始的回调。每个插件最多 128 个活动订阅，无通配符。

发布方重启期间不交付事件、不回放历史；仍在运行的消费方订阅在提供方恢复且契约仍匹配时继续生效。消费方重启需重新调用 subscribe。长期事实及重新同步请使用状态或查询服务；此接口不会自动启动宿主工作流。
