# @yagolive/event-kit

YAGO App Action 创建与通信工具库，支持浏览器、React、Vue 等多种环境。

## 架构

```
┌─────────────────────────────────────────────────────┐
│                   应用层 (Frameworks)                │
├───────────────────┬───────────────────┬─────────────┤
│  React            │  Vue 3            │  原生 JS     │
├───────────────────┴───────────────────┴─────────────┤
│                   桥接层 (Bridge)                     │
│               ActionBridge (注入适配器)               │
├─────────────────────────────────────────────────────┤
│                   适配器层 (Adapters)                 │
│        RNWebViewAdapter  │  MockAdapter              │
├─────────────────────────────────────────────────────┤
│                   核心层 (Core)                       │
│   ActionCreator  │  ActionType  │  ActionData       │
└─────────────────────────────────────────────────────┘
```

## 更新日志

详细更新日志请查看 [CHANGELOG](./CHANGELOG.md)。

## 安装

```bash
npm install @yagolive/event-kit
```

## AI 技能（Agent Skill）

包内自带一份**自包含**的 H5 接入规范技能，供 AI 编码助手（Claude Code、Codex 等支持 `SKILL.md` 约定的宿主）在开发 H5 活动页时直接使用。

| 项 | 说明 |
|------|------|
| 文件 | `skills/event-kit-h5-integration/SKILL.md` |
| 覆盖 | App 注入参数（ticket / language / 安全区）、postMessage 通信协议、全部 Action 定义与示例、完整页面模板、常见问题排查 |
| 独立性 | 内容自包含，无需访问 YAGO 仓库即可完成 H5 侧集成 |

加载方式（任选其一，把技能目录复制到宿主的技能目录）：

```bash
# 全局：对当前用户的所有项目生效
mkdir -p ~/.claude/skills ~/.codex/skills
cp -r node_modules/@yagolive/event-kit/skills/event-kit-h5-integration ~/.claude/skills/
cp -r node_modules/@yagolive/event-kit/skills/event-kit-h5-integration ~/.codex/skills/

# 项目级：随项目提交，团队共享
mkdir -p .claude/skills .agents/skills
cp -r node_modules/@yagolive/event-kit/skills/event-kit-h5-integration .claude/skills/
cp -r node_modules/@yagolive/event-kit/skills/event-kit-h5-integration .agents/skills/
```

Windows 下将 `cp -r` 换成 `Copy-Item -Recurse`。加载后向 AI 提出「开发 H5 活动页」「H5 接入 event-kit」类需求会自动触发该技能。

> 维护约束：Action 签名或通信协议变化时，需同步更新包内 `skills/event-kit-h5-integration/SKILL.md` 的内嵌定义与示例。

## 快速开始

### 浏览器（Script 标签）

```html
<!-- 引入完整功能包 -->
<script src="https://unpkg.com/@yagolive/event-kit/dist/js/action_bridge.umd.js"></script>
<script>
  var { ActionBridge } = window.__action_bridge__;

  // 自动检测环境并创建桥接实例
  var bridge = ActionBridge.createDefault();

  // 发送导航 Action
  bridge
    .navigate('profile', { userId: 123 })
    .then(function (result) {
      console.log('导航成功', result);
    })
    .catch(function (error) {
      console.error('导航失败', error);
    });
</script>
```

```html
<!-- 仅引入核心包（不需要通信功能时） -->
<script src="https://unpkg.com/@yagolive/event-kit/dist/js/action_creator.umd.js"></script>
<script>
  var { ActionCreator } = window.__action_creator__;

  var action = ActionCreator.createNavigateAction('home');
  console.log(action.toJson());
  // {"type":"navigate","data":{"screen":"home"}}
</script>
```

也可使用 [jsdelivr](https://www.jsdelivr.com/package/npm/@yagolive/event-kit)：

```html
<script src="https://cdn.jsdelivr.net/npm/@yagolive/event-kit/dist/js/action_bridge.umd.js"></script>
```

### React

```jsx
import {
  ActionBridgeProvider,
  useActionBridge,
} from '@yagolive/event-kit/react';
import { RNWebViewAdapter } from '@yagolive/event-kit/adapters';

// 1. 在根组件配置 Provider
function App() {
  return (
    <ActionBridgeProvider adapter={new RNWebViewAdapter()}>
      <MyPage />
    </ActionBridgeProvider>
  );
}

// 2. 在子组件中使用 Hook
function MyPage() {
  const bridge = useActionBridge();

  const goToProfile = async () => {
    try {
      const result = await bridge.navigate('profile', { userId: 123 });
      console.log('导航成功', result);
    } catch (error) {
      console.error('导航失败', error);
    }
  };

  return <button onClick={goToProfile}>查看个人资料</button>;
}
```

### Vue 3

```javascript
import { createActionBridgePlugin, useActionBridge } from '@yagolive/event-kit/vue';
import { RNWebViewAdapter } from '@yagolive/event-kit/adapters';

// 1. 安装插件
const adapter = new RNWebViewAdapter();
app.use(createActionBridgePlugin(adapter));

// 2. 在组件中使用 Composition API
export default {
  setup() {
    const bridge = useActionBridge();

    const goToProfile = async () => {
      try {
        const result = await bridge.navigate('profile', { userId: 123 });
        console.log('导航成功', result);
      } catch (error) {
        console.error('导航失败', error);
      }
    };

    return { goToProfile };
  }
}

// 3. 也可通过 $actionBridge 访问（Options API）
export default {
  methods: {
    async goToProfile() {
      const result = await this.$actionBridge.navigate('profile', { userId: 123 });
    }
  }
}
```

### ESM / CommonJS

```javascript
// ESM
import { ActionBridge, RNWebViewAdapter } from '@yagolive/event-kit';
const adapter = new RNWebViewAdapter();
const bridge = new ActionBridge(adapter);

// CommonJS
const { ActionBridge, RNWebViewAdapter } = require('@yagolive/event-kit');
const adapter = new RNWebViewAdapter();
const bridge = new ActionBridge(adapter);
```

---

## API 参考

### ActionCreator

纯逻辑工厂，无环境依赖。用于创建各种 Action 对象。

```javascript
import { ActionCreator } from '@yagolive/event-kit';
```

#### 属性

| 属性         | 类型   | 说明                                                                                                                                                                                        |
| ------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `ActionData` | `typeof ActionData` | 包含所有数据类型类：Jump, Navigate, Replace, Goback, EnterRoom, LiveDetect, Onelink, Ask, AgencyInvite, Recharge, RefreshUserInfo, Close, Config, Track, GrantBenefits, VerifyTradePassword, UploadImage     |
| `ActionType` | `typeof ActionType` | Action 类型枚举：JUMP, NAVIGATE, REPLACE, GOBACK, ENTER_ROOM, LIVE_DETECT, ONELINK, ASK, AGENCY_INVITE, RECHARGE, REFRESH_USER_INFO, CLOSE, CONFIG, TRACK, GRANT_BENEFITS, VERIFY_TRADE_PASSWORD, UPLOAD_IMAGE |

#### 工厂方法

| 方法                                                           | 参数                                     | 返回值              | 说明                                      |
| -------------------------------------------------------------- | ---------------------------------------- | ------------------- | ----------------------------------------- |
| `buildJump(path?)`                                             | path?: string                            | Jump                | 构建 Jump 对象（链式配置）                |
| `createJumpAction(path)`                                       | path: string                             | Action              | 创建跳转 Action                           |
| `createJumpActionWithData(jump)`                               | jump: Jump                               | Action              | 从 Jump 对象创建 Action                   |
| `buildNavigate(screen?, params?)`                              | screen?: string, params?: `Record<string, any>`         | Navigate            | 构建 Navigate 对象（链式配置）            |
| `createNavigateAction(screen)`                                 | screen: string                           | Action              | 创建导航 Action（无参数）                 |
| `createNavigateActionWithParams(screen, params)`               | screen: string, params: `Record<string, any>`           | Action              | 创建导航 Action（带参数）                 |
| `createNavigateActionWithData(navigate)`                       | navigate: Navigate                       | Action              | 从 Navigate 对象创建 Action               |
| `buildReplace(screen?, params?)`                               | screen?: string, params?: `Record<string, any>`         | Replace             | 构建 Replace 对象（链式配置）             |
| `createReplaceAction(screen)`                                  | screen: string                           | Action              | 创建替换导航 Action                       |
| `createReplaceActionWithParams(screen, params)`                | screen: string, params: `Record<string, any>`           | Action              | 创建替换导航 Action（带参数）             |
| `createReplaceActionWithData(replace)`                         | replace: Replace                         | Action              | 从 Replace 对象创建 Action                |
| `buildGoback()`                                                | -                                        | Goback              | 构建 Goback 对象（链式配置）              |
| `createGobackAction()`                                         | -                                        | Action              | 创建返回上一页 Action                     |
| `createGobackActionWithData(goback)`                           | goback: Goback                           | Action              | 从 Goback 对象创建 Action                 |
| `buildEnterRoom()`                                             | -                                        | EnterRoom           | 构建 EnterRoom 对象（链式配置）           |
| `createEnterRoomAction(id)`                                    | id: number                               | Action              | 创建进房 Action                           |
| `createEnterRoomActionWithData(enterRoom)`                     | enterRoom: EnterRoom                     | Action              | 从 EnterRoom 对象创建 Action              |
| `buildLiveDetect()`                                            | -                                        | LiveDetect          | 构建 LiveDetect 对象（链式配置）          |
| `createLiveDetectAction()`                                     | -                                        | Action              | 创建活体检测 Action                       |
| `createLiveDetectActionWithData(liveDetect)`                   | liveDetect: LiveDetect                   | Action              | 从 LiveDetect 对象创建 Action             |
| `buildOnelink(url?)`                                           | url?: string                             | Onelink             | 构建 Onelink 对象（链式配置）             |
| `createOnelinkAction(url)`                                     | url: string                              | Action              | 创建 Onelink Action                       |
| `createOnelinkActionWithData(onelink)`                         | onelink: Onelink                         | Action              | 从 Onelink 对象创建 Action                |
| `buildAsk(id)`                                                 | id: number                               | Ask                 | 构建 Ask 对象（链式配置）                 |
| `createAskAction(id)`                                          | id: number                               | Action              | 创建通用询问 Action                       |
| `createAskActionWithData(ask)`                                 | ask: Ask                                 | Action              | 从 Ask 对象创建 Action                    |
| `buildAgencyInvite(id, type)` | id: number, type: `AgencyInviteTypeValue` | AgencyInvite        | 构建 AgencyInvite 对象（链式配置）        |
| `createAgencyInviteAction(id, type)` | id: number, type: `AgencyInviteTypeValue` | Action              | 创建工会邀请 Action                       |
| `createAgencyInviteActionWithData(agencyInvite)`               | agencyInvite: AgencyInvite               | Action              | 从 AgencyInvite 对象创建 Action           |
| `buildRecharge()`                                              | -                                        | Recharge            | 构建 Recharge 对象（链式配置）            |
| `createRechargeAction()`                                       | -                                        | Action              | 创建充值 Action                           |
| `createRechargeActionWithData(recharge)`                       | recharge: Recharge                       | Action              | 从 Recharge 对象创建 Action               |
| `buildRefreshUserInfo()`                                       | -                                        | RefreshUserInfo     | 构建 RefreshUserInfo 对象（链式配置）     |
| `createRefreshUserInfoAction()`                                | -                                        | Action              | 创建刷新用户信息 Action                   |
| `createRefreshUserInfoActionWithData(refreshUserInfo)`         | refreshUserInfo: RefreshUserInfo         | Action              | 从 RefreshUserInfo 对象创建 Action        |
| `buildClose()`                                                 | -                                        | Close               | 构建 Close 对象（链式配置，addon）        |
| `createCloseAction()`                                          | -                                        | Action              | 创建关闭 Action（addon）                  |
| `createCloseActionWithData(close)`                             | close: Close                             | Action              | 从 Close 对象创建 Action（addon）         |
| `buildConfig()`                                                | -                                        | Config              | 构建 Config 对象（链式配置，addon）       |
| `createConfigAction()`                                         | -                                        | Action              | 创建配置 Action（addon）                  |
| `createConfigActionWithData(config)`                           | config: Config                           | Action              | 从 Config 对象创建 Action（addon）        |
| `buildTrack(name)`                                             | name: string                             | Track               | 构建 Track 对象（链式配置）               |
| `createTrackAction(name)`                                      | name: string                             | Action              | 创建统计事件上报 Action                   |
| `createTrackActionWithData(track)`                             | track: Track                             | Action              | 从 Track 对象创建 Action                  |
| `buildGrantBenefits(benefits)` | benefits: `BenefitItem[]` | GrantBenefits       | 构建 GrantBenefits 对象（链式配置）       |
| `createGrantBenefitsAction(benefits)` | benefits: `BenefitItem[]` | Action              | 创建权益下发 Action                       |
| `createGrantBenefitsActionWithData(grantBenefits)`             | grantBenefits: GrantBenefits             | Action              | 从 GrantBenefits 对象创建 Action          |
| `buildVerifyTradePassword()`                                   | -                                        | VerifyTradePassword | 构建 VerifyTradePassword 对象（链式配置） |
| `createVerifyTradePasswordAction()`                            | -                                        | Action              | 创建验证交易密码 Action                   |
| `createVerifyTradePasswordActionWithData(verifyTradePassword)` | verifyTradePassword: VerifyTradePassword | Action              | 从 VerifyTradePassword 对象创建 Action    |
| `buildUploadImage()`                                           | -                                        | UploadImage         | 构建 UploadImage 对象（链式配置）         |
| `createUploadImageAction()`                                    | -                                        | Action              | 创建图片上传 Action                       |
| `createUploadImageActionWithData(uploadImage)`                 | uploadImage: UploadImage                 | Action              | 从 UploadImage 对象创建 Action            |

#### 使用示例

```javascript
// 简单导航
const action = ActionCreator.createNavigateAction('home');
// {"type":"navigate","data":{"screen":"home"}}

// 带参数导航
const action = ActionCreator.createNavigateActionWithParams('profile', {
  userId: 123,
});
// {"type":"navigate","data":{"screen":"profile","params":{"userId":123}}}

// 进房（带回调配置）
const enterRoom = ActionCreator.buildEnterRoom()
  .setId(1001)
  .setBack(true)
  .setText('我的房间')
  .addOpenGiftPopupCallback(
    new ActionCreator.ActionData.EnterRoom.OpenGiftPopupCallback().setId(1),
  );
const action = ActionCreator.createEnterRoomActionWithData(enterRoom);
// {"type":"enter_room","data":{"text":"我的房间","id":1001,"back":true,"callbacks":{"open_gift_popup":{"id":1}}}}

// Onelink
const action = ActionCreator.createOnelinkAction('https://yago.app/room/123');
```

### ActionType

Action 类型枚举。

```javascript
import { ActionType } from '@yagolive/event-kit';

ActionType.JUMP; // 'jump'
ActionType.NAVIGATE; // 'navigate'
ActionType.REPLACE; // 'replace'
ActionType.GOBACK; // 'goback'
ActionType.ENTER_ROOM; // 'enter_room'
ActionType.LIVE_DETECT; // 'live_detect'
ActionType.ONELINK; // 'onelink'
ActionType.ASK; // 'ask'
ActionType.AGENCY_INVITE; // 'agency_invite'
ActionType.RECHARGE; // 'recharge'
ActionType.REFRESH_USER_INFO; // 'refresh_user_info'
ActionType.CLOSE; // 'close'   (addon)
ActionType.CONFIG; // 'config'  (addon)
ActionType.TRACK; // 'track'
ActionType.GRANT_BENEFITS; // 'grant_benefits'
ActionType.VERIFY_TRADE_PASSWORD; // 'verify_trade_password'
ActionType.UPLOAD_IMAGE; // 'upload_image'
```

### ActionBridge

统一桥接接口，通过注入适配器实现跨环境通信。

```javascript
import { ActionBridge, RNWebViewAdapter } from '@yagolive/event-kit';

const adapter = new RNWebViewAdapter();
const bridge = new ActionBridge(adapter);
```

#### 构造函数

```javascript
new ActionBridge(adapter, options?)
```

| 参数    | 类型    | 必填 | 说明                                   |
| ------- | ------- | ---- | -------------------------------------- |
| adapter | Adapter | 是   | 适配器实例，必须实现 `sendAction` 方法 |
| options | AdapterOptions | 否 | 配置项（保留） |

#### 属性

| 属性            | 类型   | 说明                   |
| --------------- | ------ | ---------------------- |
| `ActionCreator` | `typeof ActionCreator` | ActionCreator 工厂引用 |
| `ActionType` | `typeof ActionType` | ActionType 枚举引用 |

#### 核心方法

| 方法                            | 参数                                | 返回值  | 说明                                   |
| ------------------------------- | ----------------------------------- | ------- | -------------------------------------- |
| `sendAction(action, callback?)` | action: Action, callback?: Function | `Promise<any>` | 发送 Action，支持回调和 Promise 双模式 |
| `sendActionNoReply(action)`     | action: Action                      | void    | 发送 Action 不期待回复                 |
| `destroy()`                     | -                                   | void    | 销毁桥接实例，清理适配器资源           |

#### 便捷方法

每个便捷方法返回 Promise，内部自动创建对应 Action 并发送。返回值类型详见「返回值与结果数据」。

| 方法 | 参数 | 返回值 | 说明 |
| --- | --- | --- | --- |
| `jump(path)` | path: string | `Promise<undefined>` | 跳转 |
| `buildJump(path?)` | path?: string | Jump | 构建 Jump 对象（链式配置） |
| `createJumpActionWithData(jump)` | jump: Jump | Action | 从 Jump 对象创建 Action（不自动发送） |
| `navigate(screen, params?)` | screen: string, params?: `Record<string, any>` | `Promise<undefined>` | 导航到指定页面 |
| `buildNavigate(screen?, params?)` | screen?: string, params?: `Record<string, any>` | Navigate | 构建 Navigate 对象（链式配置） |
| `createNavigateActionWithData(navigate)` | navigate: Navigate | Action | 从 Navigate 对象创建 Action（不自动发送） |
| `replace(screen, params?)` | screen: string, params?: `Record<string, any>` | `Promise<undefined>` | 替换当前页面 |
| `buildReplace(screen?, params?)` | screen?: string, params?: `Record<string, any>` | Replace | 构建 Replace 对象（链式配置） |
| `createReplaceActionWithData(replace)` | replace: Replace | Action | 从 Replace 对象创建 Action（不自动发送） |
| `goback()` | - | `Promise<undefined>` | 返回上一页 |
| `buildGoback()` | - | Goback | 构建 Goback 对象（链式配置） |
| `createGobackActionWithData(goback)` | goback: Goback | Action | 从 Goback 对象创建 Action（不自动发送） |
| `enterRoom(id)` | id: number | `Promise<EnterRoomResult>` | 进入房间 |
| `buildEnterRoom()` | - | EnterRoom | 构建 EnterRoom 对象（链式配置） |
| `createEnterRoomAction(id)` | id: number | Action | 创建进房 Action |
| `createEnterRoomActionWithData(enterRoom)` | enterRoom: EnterRoom | Action | 从 EnterRoom 对象创建 Action（不自动发送） |
| `liveDetect()` | - | `Promise<LiveDetectResult>` | 触发活体检测 |
| `buildLiveDetect()` | - | LiveDetect | 构建 LiveDetect 对象（链式配置） |
| `createLiveDetectActionWithData(liveDetect)` | liveDetect: LiveDetect | Action | 从 LiveDetect 对象创建 Action（不自动发送） |
| `onelink(url)` | url: string | `Promise<string>` | 打开或生成 Onelink |
| `buildOnelink(url?)` | url?: string | Onelink | 构建 Onelink 对象（链式配置） |
| `createOnelinkActionWithData(onelink)` | onelink: Onelink | Action | 从 Onelink 对象创建 Action（不自动发送） |
| `ask(id, options?)` | id: number, options?: AskOptions | `Promise<boolean>` | 通用询问（邀请/审核） |
| `buildAsk(id?)` | id?: number | Ask | 构建 Ask 对象（链式配置） |
| `createAskActionWithData(ask)` | ask: Ask | Action | 从 Ask 对象创建 Action（不自动发送） |
| `agencyInvite(id, type)` | id: number, type: `AgencyInviteTypeValue` | `Promise<boolean>` | 工会邀请 |
| `buildAgencyInvite(id?, type?)` | id?: number, type?: `AgencyInviteTypeValue` | AgencyInvite | 构建 AgencyInvite 对象（链式配置） |
| `createAgencyInviteActionWithData(agencyInvite)` | agencyInvite: AgencyInvite | Action | 从 AgencyInvite 对象创建 Action（不自动发送） |
| `recharge(options?)` | options?: RechargeOptions | `Promise<RechargeOrder \| undefined>` | 充值：携带 `sku` 时直接发起内购并返回订单，否则打开充值弹窗 |
| `buildRecharge()` | - | Recharge | 构建 Recharge 对象（链式配置） |
| `createRechargeActionWithData(recharge)` | recharge: Recharge | Action | 从 Recharge 对象创建 Action（不自动发送） |
| `refreshUserInfo()` | - | `Promise<undefined>` | 刷新用户信息（触发宿主重新拉取 userInfo） |
| `buildRefreshUserInfo()` | - | RefreshUserInfo | 构建 RefreshUserInfo 对象（链式配置） |
| `createRefreshUserInfoActionWithData(refreshUserInfo)` | refreshUserInfo: RefreshUserInfo | Action | 从 RefreshUserInfo 对象创建 Action（不自动发送） |
| `close()` | - | `Promise<undefined>` | 关闭 WebView 窗口 |
| `buildClose()` | - | Close | 构建 Close 对象（链式配置） |
| `createCloseActionWithData(close)` | close: Close | Action | 从 Close 对象创建 Action（不自动发送） |
| `config(options?)` | options?: ConfigOptions | `Promise<undefined>` | 配置 WebView 主题与标题 |
| `buildConfig()` | - | Config | 构建 Config 对象（链式配置） |
| `createConfigActionWithData(config)` | config: Config | Action | 从 Config 对象创建 Action（不自动发送） |
| `track(name, params?, options?)` | name: string, params?: `Record<string, any>`, options?: `Record<string, any>` | `Promise<undefined>` | 统计事件上报 |
| `buildTrack(name)` | name: string | Track | 构建 Track 对象（链式配置） |
| `createTrackActionWithData(track)` | track: Track | Action | 从 Track 对象创建 Action（不自动发送） |
| `grantBenefits(benefits, options?)` | benefits: `BenefitItem[]`, options?: GrantBenefitsOptions | `Promise<undefined>` | 权益下发 |
| `buildGrantBenefits(benefits)` | benefits: `BenefitItem[]` | GrantBenefits | 构建 GrantBenefits 对象（链式配置） |
| `createGrantBenefitsActionWithData(grantBenefits)` | grantBenefits: GrantBenefits | Action | 从 GrantBenefits 对象创建 Action（不自动发送） |
| `verifyTradePassword()` | - | `Promise<boolean>` | 验证交易密码 |
| `buildVerifyTradePassword()` | - | VerifyTradePassword | 构建 VerifyTradePassword 对象（链式配置） |
| `createVerifyTradePasswordActionWithData(verifyTradePassword)` | verifyTradePassword: VerifyTradePassword | Action | 从 VerifyTradePassword 对象创建 Action（不自动发送） |
| `uploadImage(options?)` | options?: UploadImageOptions | `Promise<UploadImageResult>` | 图片上传 |
| `buildUploadImage()` | - | UploadImage | 构建 UploadImage 对象（链式配置） |
| `createUploadImageActionWithData(uploadImage)` | uploadImage: UploadImage | Action | 从 UploadImage 对象创建 Action（不自动发送） |

#### 静态方法

| 方法                       | 参数             | 返回值       | 说明                                   |
| -------------------------- | ---------------- | ------------ | -------------------------------------- |
| `createDefault(options?)` | options?: AdapterOptions | ActionBridge | 使用 RNWebViewAdapter 创建默认桥接实例 |
| `createWithMock(options?)` | options?: AdapterOptions | ActionBridge | 使用 MockAdapter 创建测试用桥接实例    |

#### 使用示例

```javascript
// Promise 风格（推荐）
const result = await bridge.navigate('profile', { userId: 123 });

// 回调风格（向后兼容）
bridge.sendAction(action, function (result, error) {
  if (error) console.error(error);
  else console.log(result);
});

// 复杂进房配置
const enterRoom = bridge.buildEnterRoom();
enterRoom.setId(1001).setUseReplace(true);
enterRoom.addOpenGiftPopupCallback(
  new bridge.ActionCreator.ActionData.EnterRoom.OpenGiftPopupCallback().setId(
    1,
  ),
);
const action = bridge.createEnterRoomActionWithData(enterRoom);
const result = await bridge.sendAction(action);

// 自定义单次超时(毫秒);timeout<=0 表示禁用超时
const result2 = await bridge.sendAction(action, { timeout: 5000 });
const result3 = await bridge.sendAction(action, { timeout: -1 }); // 不超时

// 销毁
bridge.destroy();
```

### 适配器

#### RNWebViewAdapter

用于 React Native WebView 环境，通过 `window.ReactNativeWebView.postMessage` 与原生端通信。

```javascript
import { RNWebViewAdapter } from '@yagolive/event-kit/adapters';
```

**构造函数选项：**

| 选项      | 类型   | 默认值 | 说明                 |
| --------- | ------ | ------ | -------------------- |
| `timeout` | number | 30000  | 请求超时时间（毫秒） |

**示例：**

```javascript
const adapter = new RNWebViewAdapter({ timeout: 15000 });
const bridge = new ActionBridge(adapter);

// 或使用快捷方法
const bridge = ActionBridge.createDefault({ timeout: 15000 });
```

**工作原理：**

1. `init()` 时自动检测 Android/iOS 平台并注册对应的 `message` 事件监听
2. `sendAction()` 通过 `window.ReactNativeWebView.postMessage()` 发送 JSON 数据
3. 原生端处理完毕后通过 `postMessage` 回传结果，适配器自动匹配回调/Promise
4. 超时未收到回复自动 reject Promise

#### MockAdapter

用于测试和开发环境，无需真实 WebView 即可模拟通信。

```javascript
import { MockAdapter } from '@yagolive/event-kit/adapters';
```

**构造函数选项：**

| 选项    | 类型   | 默认值 | 说明                 |
| ------- | ------ | ------ | -------------------- |
| `delay` | number | 0      | 模拟响应延迟（毫秒） |

**方法：**

| 方法                             | 参数                            | 说明                            |
| -------------------------------- | ------------------------------- | ------------------------------- |
| `mockResult(actionType, result)` | actionType: string, result: any | Mock 指定 Action 类型的返回值   |
| `mockError(actionType, error)`   | actionType: string, error: any  | Mock 指定 Action 类型的错误返回 |
| `getCalls()`                     | -                               | 获取所有调用记录                |
| `clearCalls()`                   | -                               | 清空调用记录                    |
| `clearMocks()`                   | -                               | 清空所有 Mock 配置              |

**示例：**

```javascript
const mock = new MockAdapter({ delay: 100 });
const bridge = new ActionBridge(mock);

// Mock 返回值
mock.mockResult('navigate', { success: true, screen: 'profile' });

// Mock 错误
mock.mockError('enter_room', new Error('房间不存在'));

// 验证调用
await bridge.navigate('profile');
const calls = mock.getCalls();
console.log(calls[0]);
// { type: 'navigate', data: { screen: 'profile' }, messageId: 'msg_...', timestamp: 1716364800000 }

// 清理
mock.clearCalls();
mock.clearMocks();
```

#### 自定义适配器

实现以下接口即可创建自定义适配器：

```javascript
class CustomAdapter {
  // 必须实现
  sendAction(action) {
    // action.type - Action 类型
    // action.data - Action 数据对象（有 toMap() 方法）
    // action.messageId - 消息 ID
    // 必须返回 Promise
    return new Promise((resolve, reject) => {
      // 发送 action 到目标环境
      // 收到回复后 resolve(result) 或 reject(error)
    });
  }

  sendActionNoReply(action) {
    // 发送 action 不期待回复
  }

  // 可选实现
  init() {
    // 初始化逻辑（ActionBridge 构造时自动调用）
  }

  destroy() {
    // 清理逻辑（bridge.destroy() 时自动调用）
  }
}

const bridge = new ActionBridge(new CustomAdapter());
```

---

## React 集成

```javascript
import {
  ActionBridgeProvider,
  useActionBridge,
} from '@yagolive/event-kit/react';
```

### ActionBridgeProvider

Context Provider 组件，为子组件提供 ActionBridge 实例。

**Props：**

| Prop       | 类型         | 说明                                    |
| ---------- | ------------ | --------------------------------------- |
| `adapter`  | Adapter      | 适配器实例（与 `bridge` 二选一）        |
| `bridge`   | ActionBridge | 已创建的桥接实例（与 `adapter` 二选一） |
| `children` | ReactNode    | 子组件                                  |

**行为：**

- 传入 `adapter` 时，Provider 内部创建 ActionBridge 实例，卸载时自动 destroy
- 传入 `bridge` 时，Provider 直接使用该实例，卸载时不会 destroy
- 都不传时，自动使用 `ActionBridge.createDefault()` 创建

### useActionBridge

Hook，获取当前 ActionBridge 实例。必须在 `ActionBridgeProvider` 内使用，否则抛出错误。

**示例：**

```jsx
function ProfileButton() {
  const bridge = useActionBridge();

  const handleClick = async () => {
    await bridge.navigate('profile', { userId: 123 });
  };

  return <button onClick={handleClick}>查看资料</button>;
}
```

---

## Vue 3 集成

```javascript
import {
  createActionBridgePlugin,
  useActionBridge,
} from '@yagolive/event-kit/vue';
```

### createActionBridgePlugin

创建 Vue 插件，安装后提供 ActionBridge 实例。

**参数：**

| 参数              | 类型                    | 说明                         |
| ----------------- | ----------------------- | ---------------------------- |
| `adapterOrBridge` | Adapter \| ActionBridge | 传入适配器或已创建的桥接实例 |

**安装后提供：**

- `inject(BRIDGE_KEY)` — 通过依赖注入获取
- `app.config.globalProperties.$actionBridge` — 全局属性访问

### useActionBridge

Composition API Hook，获取当前 ActionBridge 实例。必须在安装 `createActionBridgePlugin` 后使用。

**示例：**

```javascript
// Composition API
export default {
  setup() {
    const bridge = useActionBridge();

    const enterRoom = async (roomId) => {
      await bridge.enterRoom(roomId);
    };

    return { enterRoom };
  }
}

// Options API（通过 $actionBridge）
export default {
  methods: {
    async enterRoom(roomId) {
      await this.$actionBridge.enterRoom(roomId);
    }
  }
}
```

---

## 参数与枚举

### 枚举与字面量类型

| 类型 | 取值 | 说明 |
| --- | --- | --- |
| `AgencyInviteTypeValue` | `'to_be_member'`, `'to_be_subagency'` | 工会邀请类型 |
| `ConfigThemeValue` | `'dark'`, `'light'` | WebView 主题模式 |
| `UploadImageFileTypeValue` | `'user_avatar'`, `'room_image'`, `'other'` | 图片用途类型，默认 `other` |
| `UploadImageSourcesValue` | `'picker'`, `'camera'`, `'both'` | 图片来源方式，默认 `both` |
| `EnterRoomMatchTypeValue` | `'popular'`, `'follow'` | 随机匹配房间类型 |
| `RoomTypeValue` | `'live'`, `'chat'` | 房间类型，用于切换房间回调 |
| `GiftChunkTypeValue` | `'recommend'`, `'lucky'`, `'luxury'`, `'bag'` | 礼物分组类型，用于打开礼物面板回调 |
| `BenefitAssetTypeValue` | `0`, `1` | 权益资产类型：`0` 金币，`1` 积分 |
| `EnterRoomCallbackTypeValue` | `'open_gift_popup'`, `'open_game'`, `'open_activity'`, `'switch_room_type'` | 进房后可触发的回调类型 |

### 常用参数对象

| 类型 | 字段 | 说明 |
| --- | --- | --- |
| `AskOptions` | `title?`, `message?`, `accepted?`, `text?` | `title` 与 `message` 任一非空时弹出确认框；均为空时静默处理 |
| `RechargeOptions` | `sku?`, `text?` | 携带 `sku` 时跳过充值弹窗并直接发起 Google 内购 |
| `ConfigOptions` | `theme?`, `brandColor?`, `tintColor?`, `title?` | 配置 WebView 主题、品牌色、强调色和标题 |
| `GrantBenefitsOptions` | `title?`, `message?`, `okAction?`, `closeable?`, `duration?`, `theme?`, `text?` | 权益弹窗配置；`title` 默认 `Congratulations`，`message` 默认 `The gift will be put into your bag` |
| `UploadImageOptions` | `fileType?`, `sources?`, `cropping?`, `quality?`, `text?` | 图片上传配置；`quality` 范围 `0` 到 `1`，`1` 最佳 |

> 运行时注意：`GrantBenefitsOptions.theme` 和 `UploadImageOptions.cropping` 需要传入包内提供的 `GrantBenefits.Theme`、`UploadImage.Cropping` 实例，以便 `toMap()` 正确序列化。TS 结构类型 `GrantBenefitsThemeData`、`UploadImageCroppingData` 仅描述序列化后的数据形状。

## 返回值与结果数据

`ActionEventResultMap` 按 Action 类型描述执行结果，`ActionEventResult<T>` 可用于按类型提取结果。

| Action / 方法 | 返回类型 | 说明 |
| --- | --- | --- |
| `jump` / `navigate` / `replace` / `goback` | `undefined` | 导航类 Action 无返回数据 |
| `enter_room` | `EnterRoomResult` | 返回实际进入的房间信息 |
| `live_detect` | `LiveDetectResult` | 返回活体检测 token 和图片信息 |
| `onelink` | `string` | 返回 Onelink 结果 |
| `ask` | `boolean` | 返回用户是否接受 |
| `agency_invite` | `boolean` | 返回用户是否同意邀请 |
| `recharge` | `RechargeOrder \| undefined` | 携带 `sku` 直购时返回订单，否则 `undefined` |
| `close` / `config` | `undefined` | addon Action 无返回数据 |
| `track` | `undefined` | 统计上报无返回数据 |
| `grant_benefits` | `undefined` | 权益下发无返回数据 |
| `verify_trade_password` | `boolean` | 返回交易密码验证是否通过 |
| `upload_image` | `UploadImageResult` | 返回云图片地址或错误消息 |

### EnterRoomResult

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id?` | number | 目标房间 ID |
| `match?` | `EnterRoomMatchTypeValue` | 随机匹配类型 |
| `back?` | boolean | 是否通过返回逻辑进入当前/活跃房间 |

### LiveDetectResult

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `token` | string | 活体检测 token |
| `images?` | string | 活体检测图片信息 |

### RechargeOrder

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `id` | number | 订单 ID |
| `createdAt` | number | 创建时间戳 |
| `orderNo` | string | 订单号 |
| `outerPlanId` | string | 外部计划 ID |
| `payType` | `'google'` | 支付方式，当前为 Google Play 内购 |
| `amount` | number | 充值金额：美元 |
| `report` | boolean | 是否上报成功 |

### UploadImageResult

| 字段 | 类型 | 说明 |
| --- | --- | --- |
| `url?` | string | 已上传的云图片地址 |
| `error?` | string | 上传失败时的错误消息 |

## 数据类型

### Jump

跳转 Action 数据。

| 方法                | 参数                | 说明                    |
| ------------------- | ------------------- | ----------------------- |
| `constructor(path)` | path: string (必填) | 创建跳转数据            |
| `setText(text)`     | text: string        | 设置显示文本，返回 this |
| `setPath(path)`     | path: string (必填) | 设置跳转路径，返回 this |

### Navigate

导航 Action 数据。

| 方法                           | 参数                                   | 说明                    |
| ------------------------------ | -------------------------------------- | ----------------------- |
| `constructor(screen, params?)` | screen: string (必填), params?: `Record<string, any>` | 创建导航数据            |
| `setText(text)`                | text: string                           | 设置显示文本，返回 this |
| `setScreen(screen)`            | screen: string (必填)                  | 设置目标页面，返回 this |
| `setParams(params)`            | params: `Record<string, any>`                         | 设置导航参数，返回 this |

### Replace

替换导航 Action 数据，继承自 Navigate，API 相同。

### Goback

返回上一页 Action 数据。

| 方法            | 参数         | 说明                    |
| --------------- | ------------ | ----------------------- |
| `constructor()` | -            | 创建返回数据            |
| `setText(text)` | text: string | 设置显示文本，返回 this |

### EnterRoom

进房 Action 数据。

| 方法                            | 参数                       | 说明                            |
| ------------------------------- | -------------------------- | ------------------------------- |
| `constructor()`                 | -                          | 创建进房数据                    |
| `setText(text)`                 | text: string               | 设置显示文本，返回 this         |
| `setId(id)`                     | id: number                 | 设置房间 ID，返回 this          |
| `setMatch(match)` | match: `EnterRoomMatchTypeValue` | 设置匹配信息，返回 this         |
| `setBack(back)`                 | back: boolean              | 设置返回优先，返回 this         |
| `setUseReplace(useReplace)`     | useReplace: boolean        | 设置是否替换模式，返回 this     |
| `addOpenGiftPopupCallback(cb)`  | cb: OpenGiftPopupCallback  | 添加打开礼物弹窗回调，返回 this |
| `addOpenGameCallback(cb)`       | cb: OpenGameCallback       | 添加打开游戏回调，返回 this     |
| `addOpenActivityCallback(cb)`   | cb: OpenActivityCallback   | 添加打开活动回调，返回 this     |
| `addSwitchRoomTypeCallback(cb)` | cb: SwitchRoomTypeCallback | 添加切换房间类型回调，返回 this |

**静态属性：**

| 属性                               | 说明                                                                      |
| ---------------------------------- | ------------------------------------------------------------------------- |
| `EnterRoom.CallbackType`           | 回调类型枚举：OPEN_GIFT_POPUP, OPEN_GAME, OPEN_ACTIVITY, SWITCH_ROOM_TYPE |
| `EnterRoom.OpenGiftPopupCallback`  | 礼物弹窗回调类                                                            |
| `EnterRoom.OpenGameCallback`       | 游戏回调类                                                                |
| `EnterRoom.OpenActivityCallback`   | 活动回调类                                                                |
| `EnterRoom.SwitchRoomTypeCallback` | 切换房间类型回调类                                                        |

### LiveDetect

活体检测 Action 数据。

| 方法            | 参数         | 说明                    |
| --------------- | ------------ | ----------------------- |
| `constructor()` | -            | 创建活体检测数据        |
| `setText(text)` | text: string | 设置显示文本，返回 this |

### Onelink

Onelink Action 数据。

| 方法                | 参数               | 说明                            |
| ------------------- | ------------------ | ------------------------------- |
| `constructor(url?)` | url?: string       | 创建 Onelink 数据               |
| `setText(text)`     | text: string       | 设置显示文本，返回 this         |
| `setUrl(url)`       | url: string (必填) | 设置链接 URL，返回 this         |
| `setShare(share)`   | share: boolean     | 设置是否显示分享弹窗，返回 this |

### Ask

通用询问 Action 数据，用于邀请、审核等需要用户确认/拒绝的场景。

> **App 侧消费语义**：当 `title` 或 `message` 任一非空时，app 侧弹出 `ConfirmDialog` 让用户确认；均为空则进入静默模式，由调用方（如系统消息卡片）在界面上直接展示 Accept/Reject 按钮。

| 方法                    | 参数              | 说明                                                                    |
| ----------------------- | ----------------- | ----------------------------------------------------------------------- |
| `constructor(id)`       | id: number (必填) | 创建通用询问数据                                                        |
| `setText(text)`         | text: string      | 设置显示文本，返回 this                                                 |
| `setId(id)`             | id: number        | 设置询问 ID，返回 this                                                  |
| `setTitle(title)`       | title: string     | 设置询问标题，返回 this                                                 |
| `setMessage(message)`   | message: string   | 设置询问内容，返回 this                                                 |
| `setAccepted(accepted)` | accepted: boolean | 设置当前回复状态（true=已接受，false=已拒绝，未设置=未回复），返回 this |

### AgencyInvite

工会邀请 Action 数据。

| 方法                        | 参数                                   | 说明                                                           |
| --------------------------- | -------------------------------------- | -------------------------------------------------------------- |
| `constructor(id, type)` | id: number (必填), type: `AgencyInviteTypeValue` (必填) | 创建工会邀请数据                                               |
| `setText(text)`             | text: string                           | 设置显示文本，返回 this                                        |
| `setId(id)`                 | id: number                             | 设置邀请 ID，返回 this                                         |
| `setType(type)` | type: `AgencyInviteTypeValue` | 设置邀请类型（'to_be_member' \| 'to_be_subagency'），返回 this |
| `setTitle(title)`           | title: string                          | 设置邀请标题，返回 this                                        |
| `setMessage(message)`       | message: string                        | 设置邀请内容，返回 this                                        |
| `setAgencyInfo(agencyInfo)` | agencyInfo: AgencyInfo                 | 设置工会信息，返回 this                                        |
| `setAccepted(accepted)`     | accepted: boolean                      | 设置邀请状态，返回 this                                        |

**静态属性：**

| 属性                            | 说明                                        |
| ------------------------------- | ------------------------------------------- |
| `AgencyInvite.AgencyInviteType` | 邀请类型枚举：TO_BE_MEMBER, TO_BE_SUBAGENCY |
| `AgencyInvite.AgencyInfo`       | 工会信息内部类                              |

**AgencyInfo 内部类：**

| 方法                          | 参数                | 说明                          |
| ----------------------------- | ------------------- | ----------------------------- |
| `setId(id)`                   | id: string          | 设置工会 ID，返回 this        |
| `setName(name)`               | name: string        | 设置工会名称，返回 this       |
| `setOwnerId(ownerId)`         | ownerId: string     | 设置工会长 ID，返回 this      |
| `setOwnerName(ownerName)`     | ownerName: string   | 设置工会长名称，返回 this     |
| `setOwnerAvatar(ownerAvatar)` | ownerAvatar: string | 设置工会长头像 URL，返回 this |

### Recharge

充值操作 Action 数据。携带 `sku` 时（Android）跳过充值弹窗直接发起 Google 内购，执行结果返回创建的订单；iOS 暂不支持直接内购。

| 方法            | 参数         | 说明                                                              |
| --------------- | ------------ | ----------------------------------------------------------------- |
| `constructor()` | -            | 创建充值数据                                                      |
| `setText(text)` | text: string | 设置显示文本，返回 this                                           |
| `setSku(sku)`   | sku: string  | 设置外部产品 ID（Google Play SKU），携带时直接发起内购，返回 this |

### RefreshUserInfo

刷新用户信息 Action 数据。触发宿主重新拉取用户信息（如领奖后金币入账）。

| 方法            | 参数         | 说明                    |
| --------------- | ------------ | ----------------------- |
| `constructor()` | -            | 创建刷新用户信息数据    |
| `setText(text)` | text: string | 设置显示文本，返回 this |

### Close（addon 附加）

关闭 WebView 窗口 Action 数据。来源于 `addon.ts` 的 `AddonAction`，由宿主容器扩展。

| 方法            | 参数         | 说明                    |
| --------------- | ------------ | ----------------------- |
| `constructor()` | -            | 创建 Close 数据         |
| `setText(text)` | text: string | 设置显示文本，返回 this |

### Config（addon 附加）

配置 WebView 主题色等参数 Action 数据。来源于 `addon.ts` 的 `AddonAction`，由宿主容器扩展。

| 方法                        | 参数                     | 说明                    |
| --------------------------- | ------------------------ | ----------------------- |
| `constructor()`             | -                        | 创建 Config 数据        |
| `setText(text)`             | text: string             | 设置显示文本，返回 this |
| `setTheme(theme)`           | theme: 'dark' \| 'light' | 设置主题，返回 this     |
| `setBrandColor(brandColor)` | brandColor: string       | 设置品牌色，返回 this   |
| `setTintColor(tintColor)`   | tintColor: string        | 设置主题色，返回 this   |
| `setTitle(title)`           | title: string            | 设置页面标题，返回 this |

**静态属性**:

- `Config.Theme.DARK` = `'dark'`
- `Config.Theme.LIGHT` = `'light'`

### Track

统计事件上报 Action 数据。

| 方法                  | 参数                         | 说明                    |
| --------------------- | ---------------------------- | ----------------------- |
| `constructor(name)`   | name: string (必填)          | 创建 Track 数据         |
| `setText(text)`       | text: string                 | 设置显示文本，返回 this |
| `setName(name)`       | name: string (必填)          | 设置事件名，返回 this   |
| `setParams(params)`   | params: Record<string, any>  | 设置事件参数，返回 this |
| `setOptions(options)` | options: Record<string, any> | 设置事件选项，返回 this |

### GrantBenefits

权益下发 Action 数据。

| 方法                      | 参数                   | 说明                                |
| ------------------------- | ---------------------- | ----------------------------------- |
| `constructor(benefits)` | benefits: `BenefitItem[]` (必填) | 创建 GrantBenefits 数据             |
| `setText(text)`           | text: string           | 设置显示文本，返回 this             |
| `setBenefits(benefits)` | benefits: `BenefitItem[]` (必填) | 设置权益列表，返回 this             |
| `setTitle(title)`         | title: string          | 设置弹窗标题，返回 this             |
| `setMessage(message)`     | message: string        | 设置弹窗消息，返回 this             |
| `setOkAction(okAction)`   | okAction: Action       | 设置确认按钮动作，返回 this         |
| `setCloseable(closeable)` | closeable: boolean     | 设置是否允许关闭，返回 this         |
| `setDuration(duration)`   | duration: number       | 设置自动关闭时间（毫秒），返回 this |
| `setTheme(theme)` | theme: `GrantBenefitsTheme` | 设置弹窗主题配置，返回 this         |

**静态属性：**

| 属性                  | 说明               |
| --------------------- | ------------------ |
| `GrantBenefits.Theme` | 弹窗主题配置内部类 |

**Theme 内部类：**

| 方法                          | 参数                     | 说明                                |
| ----------------------------- | ------------------------ | ----------------------------------- |
| `setImage(image)`             | image: string (必填)     | 设置主题图片，返回 this             |
| `setTintColor(tintColor)`     | tintColor: string (必填) | 设置主题色，返回 this               |
| `setButtonImage(buttonImage)` | buttonImage: string      | 设置按钮图片，返回 this             |
| `setTopInset(topInset)`       | topInset: number         | 设置头部高度（默认 196），返回 this |

### VerifyTradePassword

验证交易密码 Action 数据。

| 方法            | 参数         | 说明                    |
| --------------- | ------------ | ----------------------- |
| `constructor()` | -            | 创建验证交易密码数据    |
| `setText(text)` | text: string | 设置显示文本，返回 this |

### UploadImage

图片上传 Action 数据。

| 方法                    | 参数                                    | 说明                                      |
| ----------------------- | --------------------------------------- | ----------------------------------------- |
| `constructor()`         | -                                       | 创建图片上传数据                          |
| `setText(text)`         | text: string                            | 设置显示文本，返回 this                   |
| `setFileType(fileType)` | fileType: `UploadImageFileTypeValue` | 设置图片类型（按用途分类），返回 this     |
| `setSources(sources)` | sources: `UploadImageSourcesValue` | 设置图片来源方式，返回 this               |
| `setCropping(cropping)` | cropping: `UploadImageCropping` | 设置裁剪配置（启用裁剪时设置），返回 this |
| `setQuality(quality)`   | quality: number                         | 设置压缩质量（0-1，1 最佳），返回 this    |

**静态属性：**

- `UploadImage.FileType.USER_AVATAR` = `'user_avatar'`
- `UploadImage.FileType.ROOM_IMAGE` = `'room_image'`
- `UploadImage.FileType.OTHER` = `'other'`
- `UploadImage.Sources.PICKER` = `'picker'`
- `UploadImage.Sources.CAMERA` = `'camera'`
- `UploadImage.Sources.BOTH` = `'both'`
- `UploadImage.Cropping` | 裁剪配置内部类

**Cropping 内部类：**

| 方法                | 参数           | 说明                          |
| ------------------- | -------------- | ----------------------------- |
| `setWidth(width)`   | width: number  | 设置裁剪后图片宽度，返回 this |
| `setHeight(height)` | height: number | 设置裁剪后图片高度，返回 this |

### Action

Action 对象，封装类型和数据。

| 方法                      | 参数                               | 说明                                        |
| ------------------------- | ---------------------------------- | ------------------------------------------- |
| `constructor(type, data)` | type: ActionType, data: ActionData | 创建 Action                                 |
| `setType(type)`           | type: ActionType                   | 设置 Action 类型，返回 this                 |
| `setData(data)`           | data: ActionData                   | 设置 Action 数据，返回 this                 |
| `setBaseData(text)`       | text: string                       | 设置数据的 text 字段（便捷方法），返回 this |
| `toJson()`                | -                                  | 序列化为 JSON 字符串                        |

---

## 构建

```bash
# 构建所有 UMD 文件
npm run build

# 仅构建核心包
npm run build:core

# 仅构建完整包
npm run build:bridge

# 监听模式（开发时使用）
npm run build:watch
```

**产出文件：**

| 文件                            | 说明                                        | 全局变量             |
| ------------------------------- | ------------------------------------------- | -------------------- |
| `dist/js/action_creator.umd.js` | 核心包（仅 ActionCreator）                  | `__action_creator__` |
| `dist/js/action_bridge.umd.js`  | 完整包（ActionCreator + Bridge + Adapters） | `__action_bridge__`  |
