{"_id":"@agentunion/aun-browser","name":"@agentunion/aun-browser","dist-tags":{"latest":"0.2.11"},"versions":{"0.2.11":{"name":"@agentunion/aun-browser","version":"0.2.11","description":"AUN Protocol Core SDK for Browser","type":"module","main":"dist/index.js","types":"dist/index.d.ts","browser":"dist/index.js","exports":{".":{"import":"./dist/index.js","types":"./dist/index.d.ts"}},"license":"Apache-2.0","scripts":{"build":"tsc","test":"vitest run --environment jsdom","test:unit":"vitest run --environment jsdom tests/unit","test:integration":"vitest run --environment jsdom tests/integration","test:e2e":"npm run build && playwright test --config=playwright.agentid-local.config.ts tests/e2e-browser/e2ee.spec.ts --reporter=line","test:e2e:smoke":"npm run build && playwright test --config=playwright.agentid-local.config.ts tests/e2e-browser/e2ee.spec.ts --grep \"SDK 创建 AID\" --reporter=line"},"devDependencies":{"@playwright/test":"^1.59.1","esbuild":"^0.24.0","fake-indexeddb":"^6.2.5","jsdom":"^25.0.0","typescript":"^5.6.0","vitest":"^2.0.0"},"_id":"@agentunion/aun-browser@0.2.11","gitHead":"a0e154bc1800470afd348dd7d1775d01093b2c31","_nodeVersion":"22.19.0","_npmVersion":"11.6.0","dist":{"integrity":"sha512-HfUbajJx2Pg1b5SCBwbHlTejno/6GobTCjBmch/dWwr95GgGq1leTATzt04E83TK0CWC1u+mu/EEN/vy4bYSOw==","shasum":"b1593d8f162c2aec37c63b9db7ec9b3cbee6e698","tarball":"https://registry.npmjs.org/@agentunion/aun-browser/-/aun-browser-0.2.11.tgz","fileCount":82,"unpackedSize":1034670,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIECEwU9jSjU8gw3RYAPQq9pRBpD8AxXvlYSMidv3LQyGAiBJqQyni3tCIpWpe+Adi3BJYINJP1JU8nyp1RyYMQar1A=="}]},"_npmUser":{"name":"agentunion","email":"toleiliang@163.com"},"directories":{},"maintainers":[{"name":"agentunion","email":"toleiliang@163.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/aun-browser_0.2.11_1777379454670_0.6016420550734742"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-28T12:30:54.603Z","0.2.11":"2026-04-28T12:30:54.888Z","modified":"2026-04-28T12:30:55.124Z"},"maintainers":[{"name":"agentunion","email":"toleiliang@163.com"}],"description":"AUN Protocol Core SDK for Browser","license":"Apache-2.0","readme":"# AUN JS SDK 接口接入文档\r\n\r\n本文档只描述 `aun-sdk-core/js` 的对外接口、接入步骤和调用约定。\r\n\r\n## 1. 运行环境\r\n\r\n适用运行环境：\r\n\r\n- 浏览器\r\n- WebView\r\n- Electron Renderer\r\n\r\n运行时依赖：\r\n\r\n- `fetch`\r\n- `WebSocket`\r\n- `crypto.subtle`\r\n- `IndexedDB`\r\n- `localStorage`\r\n\r\n## 2. 导入\r\n\r\n```ts\r\nimport {\r\n  AUNClient,\r\n  AUNError,\r\n  AuthError,\r\n  ConnectionError,\r\n  ValidationError,\r\n} from '@aun/core-browser';\r\n```\r\n\r\n本地调试也可以直接从构建产物导入：\r\n\r\n```ts\r\nimport { AUNClient } from './dist/index.js';\r\n```\r\n\r\n## 3. 快速开始\r\n\r\n```ts\r\nimport { AUNClient } from '@aun/core-browser';\r\n\r\nconst client = new AUNClient({\r\n  aunPath: 'aun-web',\r\n  discoveryPort: 18443,\r\n  seedPassword: 'demo-seed',\r\n});\r\n\r\nawait client.auth.createAid({\r\n  aid: 'alice.agentid.pub',\r\n});\r\n\r\nconst auth = await client.auth.authenticate({\r\n  aid: 'alice.agentid.pub',\r\n});\r\n\r\nawait client.connect({\r\n  ...auth,\r\n  slot_id: 'web-main',\r\n});\r\n\r\nawait client.call('message.send', {\r\n  to: 'bob.agentid.pub',\r\n  payload: { type: 'text', text: 'hello' },\r\n});\r\n```\r\n\r\n## 4. `AUNClient`\r\n\r\n### 4.1 构造函数\r\n\r\n```ts\r\nconst client = new AUNClient(config?);\r\n```\r\n\r\n配置项：\r\n\r\n| 字段 | 类型 | 默认值 | 说明 |\r\n| --- | --- | --- | --- |\r\n| `aunPath` | `string` | `aun` | 本地存储命名标识 |\r\n| `rootCaPem` | `string \\| null` | `null` | 自定义根证书 PEM |\r\n| `seedPassword` | `string \\| null` | `null` | SecretStore 派生种子 |\r\n| `discoveryPort` | `number \\| null` | `null` | Gateway 发现端口 |\r\n| `epochAutoRotateInterval` | `number` | `0` | 群组 epoch 自动轮换间隔，秒 |\r\n| `oldEpochRetentionSeconds` | `number` | `604800` | 旧 epoch 保留时长 |\r\n| `requireForwardSecrecy` | `boolean` | `true` | P2P 加密是否强制要求前向保密 |\r\n| `replayWindowSeconds` | `number` | `300` | 本地防重放时间窗口 |\r\n\r\n说明：\r\n\r\n- `groupE2ee` 在浏览器 SDK 中始终强制开启。\r\n- 新成员加入、审批通过或邀请码入群后，浏览器 SDK 固定触发群组 epoch 轮换。\r\n- `verify_ssl=false` 在浏览器 SDK 中不允许使用。\r\n\r\n### 4.2 属性\r\n\r\n#### `client.aid`\r\n\r\n当前已登录的 AID。\r\n\r\n类型：\r\n\r\n```ts\r\nstring | null\r\n```\r\n\r\n#### `client.state`\r\n\r\n当前连接状态。\r\n\r\n类型：\r\n\r\n```ts\r\n'idle' | 'connecting' | 'authenticating' | 'connected' | 'disconnected' | 'reconnecting' | 'terminal_failed' | 'closed'\r\n```\r\n\r\n#### `client.gatewayUrl`\r\n\r\n当前 Gateway URL，可读写。\r\n\r\n类型：\r\n\r\n```ts\r\nstring | null\r\n```\r\n\r\n#### `client.auth`\r\n\r\n认证命名空间，见下文 `AuthNamespace`。\r\n\r\n#### `client.discovery`\r\n\r\nGateway 发现器实例。\r\n\r\n#### `client.e2ee`\r\n\r\nP2P E2EE 管理器实例。\r\n\r\n#### `client.groupE2ee`\r\n\r\n群组 E2EE 管理器实例。\r\n\r\n### 4.3 `client.connect(auth, options?)`\r\n\r\n建立 Gateway 会话。\r\n\r\n```ts\r\nawait client.connect(auth, options?);\r\n```\r\n\r\n`auth` 必填字段：\r\n\r\n| 字段 | 类型 | 说明 |\r\n| --- | --- | --- |\r\n| `access_token` | `string` | 访问令牌 |\r\n| `gateway` | `string` | Gateway WebSocket 地址 |\r\n\r\n`auth/options` 可选字段：\r\n\r\n| 字段 | 类型 | 说明 |\r\n| --- | --- | --- |\r\n| `slot_id` | `string` | 实例隔离 ID |\r\n| `delivery_mode` | `object` | 连接级消息投递模式 |\r\n| `queue_routing` | `string` | 队列路由策略 |\r\n| `affinity_ttl_ms` | `number` | sender affinity TTL |\r\n| `auto_reconnect` | `boolean` | 是否自动重连 |\r\n| `heartbeat_interval` | `number` | 心跳间隔，秒 |\r\n| `token_refresh_before` | `number` | 提前刷新 token 的秒数 |\r\n| `retry` | `object` | 重连退避配置 |\r\n| `timeouts` | `object` | connect/call/http 超时配置 |\r\n\r\n示例：\r\n\r\n```ts\r\nawait client.connect(\r\n  {\r\n    ...auth,\r\n    slot_id: 'web-main',\r\n    delivery_mode: {\r\n      mode: 'queue',\r\n      routing: 'sender_affinity',\r\n      affinity_ttl_ms: 900000,\r\n    },\r\n  },\r\n  {\r\n    auto_reconnect: true,\r\n    heartbeat_interval: 30,\r\n    token_refresh_before: 60,\r\n    retry: {\r\n      initial_delay: 0.5,\r\n      max_delay: 30,\r\n      max_attempts: 0,\r\n    },\r\n    timeouts: {\r\n      connect: 5,\r\n      call: 10,\r\n      http: 30,\r\n    },\r\n  },\r\n);\r\n```\r\n\r\n### 4.4 `client.disconnect()`\r\n\r\n断开当前连接，但保留本地身份和缓存状态，可再次 `connect()`。\r\n\r\n```ts\r\nawait client.disconnect();\r\n```\r\n\r\n### 4.5 `client.close()`\r\n\r\n彻底关闭客户端连接，并停止后台任务。\r\n\r\n```ts\r\nawait client.close();\r\n```\r\n\r\n### 4.6 `client.call(method, params?)`\r\n\r\n发起 RPC 调用。\r\n\r\n```ts\r\nconst result = await client.call(method, params?);\r\n```\r\n\r\n说明：\r\n\r\n- 只能在 `connected` 状态下调用。\r\n- 内部方法会被 SDK 拦截，不能直接调用。\r\n- `message.send` 默认自动加密。\r\n- `group.send` 默认自动加密。\r\n- `message.pull` / `group.pull` 返回的消息会自动解密。\r\n- `group.*` 关键操作会自动附加客户端签名。\r\n\r\n### 4.7 便捷方法\r\n\r\n#### `client.ping(params?)`\r\n\r\n```ts\r\nawait client.ping();\r\n```\r\n\r\n等价于：\r\n\r\n```ts\r\nawait client.call('meta.ping', params ?? {});\r\n```\r\n\r\n#### `client.status(params?)`\r\n\r\n```ts\r\nawait client.status();\r\n```\r\n\r\n#### `client.trustRoots(params?)`\r\n\r\n```ts\r\nawait client.trustRoots();\r\n```\r\n\r\n### 4.8 `client.on(event, handler)`\r\n\r\n订阅事件。\r\n\r\n```ts\r\nconst sub = client.on('message.received', (event) => {\r\n  console.log(event);\r\n});\r\n\r\nsub.unsubscribe();\r\n```\r\n\r\n### 4.9 `client.listIdentities()`\r\n\r\n列出本地已存储的身份摘要。\r\n\r\n```ts\r\nconst identities = await client.listIdentities();\r\n```\r\n\r\n返回值示例：\r\n\r\n```ts\r\n[\r\n  {\r\n    aid: 'alice.agentid.pub',\r\n    metadata: {\r\n      access_token: '...',\r\n      refresh_token: '...',\r\n    },\r\n  },\r\n]\r\n```\r\n\r\n## 5. `AuthNamespace`\r\n\r\n### 5.1 `client.auth.createAid(params)`\r\n\r\n注册新 AID。\r\n\r\n```ts\r\nconst result = await client.auth.createAid({\r\n  aid: 'alice.agentid.pub',\r\n});\r\n```\r\n\r\n请求参数：\r\n\r\n| 字段 | 类型 | 必填 | 说明 |\r\n| --- | --- | --- | --- |\r\n| `aid` | `string` | 是 | 要注册的 AID |\r\n\r\n返回值：\r\n\r\n```ts\r\n{\r\n  aid: string,\r\n  cert_pem: string,\r\n  gateway: string,\r\n}\r\n```\r\n\r\n### 5.2 `client.auth.authenticate(params?)`\r\n\r\n对已注册 AID 做认证，返回连接参数。\r\n\r\n```ts\r\nconst auth = await client.auth.authenticate({\r\n  aid: 'alice.agentid.pub',\r\n});\r\n```\r\n\r\n请求参数：\r\n\r\n| 字段 | 类型 | 必填 | 说明 |\r\n| --- | --- | --- | --- |\r\n| `aid` | `string` | 否 | 目标 AID；未传时使用当前本地身份 |\r\n\r\n返回值：\r\n\r\n```ts\r\n{\r\n  aid: string,\r\n  access_token: string,\r\n  refresh_token?: string,\r\n  expires_at?: number,\r\n  gateway: string,\r\n}\r\n```\r\n\r\n### 5.3 `client.auth.uploadAgentMd(content)`\r\n\r\n上传当前 AID 的 `agent.md`。\r\n\r\n```ts\r\nawait client.auth.uploadAgentMd('# Alice\\n');\r\n```\r\n\r\n### 5.4 `client.auth.downloadAgentMd(aid)`\r\n\r\n下载指定 AID 的 `agent.md`。\r\n\r\n```ts\r\nconst markdown = await client.auth.downloadAgentMd('bob.agentid.pub');\r\n```\r\n\r\n### 5.5 证书相关 RPC\r\n\r\n#### `client.auth.downloadCert(params?)`\r\n\r\n```ts\r\nawait client.auth.downloadCert({ aid: 'alice.agentid.pub' });\r\n```\r\n\r\n#### `client.auth.requestCert(params)`\r\n\r\n```ts\r\nawait client.auth.requestCert({ csr: '...' });\r\n```\r\n\r\n#### `client.auth.renewCert(params?)`\r\n\r\n```ts\r\nawait client.auth.renewCert();\r\n```\r\n\r\n#### `client.auth.rekey(params?)`\r\n\r\n```ts\r\nawait client.auth.rekey();\r\n```\r\n\r\n#### `client.auth.trustRoots(params?)`\r\n\r\n```ts\r\nawait client.auth.trustRoots();\r\n```\r\n\r\n## 6. P2P 消息接口\r\n\r\n### 7.1 发送消息 `message.send`\r\n\r\n```ts\r\nawait client.call('message.send', {\r\n  to: 'bob.agentid.pub',\r\n  payload: {\r\n    type: 'text',\r\n    text: 'hello',\r\n  },\r\n});\r\n```\r\n\r\n默认行为：\r\n\r\n- `encrypt` 默认是 `true`\r\n- SDK 优先使用 prekey 加密\r\n- 若取不到 prekey，会按配置决定是否允许降级到 `long_term_key`\r\n\r\n显式明文发送：\r\n\r\n```ts\r\nawait client.call('message.send', {\r\n  to: 'bob.agentid.pub',\r\n  payload: { type: 'text', text: 'plain text' },\r\n  encrypt: false,\r\n});\r\n```\r\n\r\n参数限制：\r\n\r\n- 不允许传 `persist`\r\n- 不允许传消息级 `delivery_mode`\r\n- 不允许传 `queue_routing`\r\n- 不允许传 `affinity_ttl_ms`\r\n- `to` 不能是 `group.{issuer}`\r\n\r\n### 7.2 拉取消息 `message.pull`\r\n\r\n```ts\r\nconst result = await client.call('message.pull', {\r\n  after_seq: 0,\r\n  limit: 50,\r\n});\r\n```\r\n\r\nSDK 自动行为：\r\n\r\n- 自动注入当前实例 `device_id` 和 `slot_id`\r\n- 自动解密返回消息\r\n- 自动更新 contiguous seq\r\n- 自动发送 `message.ack`\r\n\r\n## 7. 群组消息接口\r\n\r\n### 8.1 发送群消息 `group.send`\r\n\r\n```ts\r\nawait client.call('group.send', {\r\n  group_id: 'group-123',\r\n  payload: {\r\n    type: 'text',\r\n    text: 'hello group',\r\n  },\r\n});\r\n```\r\n\r\n默认行为：\r\n\r\n- `encrypt` 默认是 `true`\r\n- 自动调用群组 E2EE 加密\r\n- 自动附加客户端签名\r\n\r\n### 8.2 拉取群消息 `group.pull`\r\n\r\n```ts\r\nconst result = await client.call('group.pull', {\r\n  group_id: 'group-123',\r\n  after_seq: 0,\r\n  limit: 50,\r\n});\r\n```\r\n\r\nSDK 自动行为：\r\n\r\n- 自动解密返回消息\r\n- 自动更新群消息 contiguous seq\r\n- 自动发送 `group.ack_messages`\r\n\r\n### 8.3 自动编排\r\n\r\nSDK 内部已自动处理以下群组 E2EE 场景：\r\n\r\n- `group.create` 后自动创建首个 epoch\r\n- `group.add_member` 后自动轮换 epoch 并分发新密钥\r\n- `group.kick` 后自动轮换 epoch\r\n- 审批通过后自动轮换 epoch 并分发新密钥\r\n- 群消息解密失败时自动尝试密钥恢复\r\n\r\n## 8. 事件\r\n\r\n常用事件：\r\n\r\n| 事件名 | 说明 |\r\n| --- | --- |\r\n| `connection.state` | 连接状态变化 |\r\n| `connection.error` | 连接错误 |\r\n| `connection.challenge` | Gateway challenge |\r\n| `token.refreshed` | token 自动刷新成功 |\r\n| `message.received` | P2P 消息，SDK 已优先自动解密 |\r\n| `message.undecryptable` | 无法解密的 P2P 消息 |\r\n| `message.recalled` | 撤回事件 |\r\n| `message.ack` | ack 事件 |\r\n| `group.message_created` | 群消息，SDK 已优先自动解密 |\r\n| `group.message_undecryptable` | 无法解密的群消息 |\r\n| `group.changed` | 群组事件 |\r\n| `notification` | 未被 SDK 特殊处理的通知 |\r\n| `e2ee.degraded` | P2P 加密降级事件 |\r\n| `e2ee.orchestration_error` | 群组 E2EE 编排错误 |\r\n\r\n示例：\r\n\r\n```ts\r\nclient.on('connection.state', (evt) => {\r\n  console.log('connection.state', evt);\r\n});\r\n\r\nclient.on('message.received', (evt) => {\r\n  console.log('message.received', evt);\r\n});\r\n\r\nclient.on('group.message_created', (evt) => {\r\n  console.log('group.message_created', evt);\r\n});\r\n```\r\n\r\n## 9. 错误类型\r\n\r\n常用错误类型：\r\n\r\n- `AUNError`\r\n- `ConnectionError`\r\n- `TimeoutError`\r\n- `AuthError`\r\n- `PermissionError`\r\n- `ValidationError`\r\n- `NotFoundError`\r\n- `RateLimitError`\r\n- `StateError`\r\n- `SerializationError`\r\n- `SessionError`\r\n- `GroupError`\r\n- `E2EEError`\r\n\r\n示例：\r\n\r\n```ts\r\ntry {\r\n  await client.call('message.send', {\r\n    to: 'bob.agentid.pub',\r\n    payload: { type: 'text', text: 'hello' },\r\n  });\r\n} catch (error) {\r\n  if (error instanceof ValidationError) {\r\n    console.error('参数错误', error.message);\r\n  } else if (error instanceof AuthError) {\r\n    console.error('认证错误', error.message);\r\n  } else if (error instanceof ConnectionError) {\r\n    console.error('连接错误', error.message);\r\n  } else {\r\n    console.error(error);\r\n  }\r\n}\r\n```\r\n\r\n## 10. 最小接入模板\r\n\r\n```ts\r\nimport { AUNClient } from '@aun/core-browser';\r\n\r\nexport async function bootstrapAun() {\r\n  const client = new AUNClient({\r\n    aunPath: 'aun-web',\r\n    discoveryPort: 18443,\r\n    seedPassword: 'demo-seed',\r\n  });\r\n\r\n  client.on('connection.state', (evt) => {\r\n    console.log('[aun] state', evt);\r\n  });\r\n\r\n  const auth = await client.auth.authenticate({\r\n    aid: 'alice.agentid.pub',\r\n  });\r\n\r\n  await client.connect({\r\n    ...auth,\r\n    slot_id: 'web-main',\r\n  });\r\n\r\n  return client;\r\n}\r\n```\r\n","readmeFilename":"README.md","_rev":"1-e37463a4ac6f8f255b8c90aa7271e67b"}