@coze/realtime-api 0.0.4 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Coze Realtime API
2
2
 
3
+ [![npm version](https://img.shields.io/npm/v/@coze/realtime-api.svg)](https://www.npmjs.com/package/@coze/realtime-api)
4
+ [![npm downloads](https://img.shields.io/npm/dm/@coze/realtime-api.svg)](https://www.npmjs.com/package/@coze/realtime-api)
5
+ [![license](https://img.shields.io/npm/l/@coze/realtime-api.svg)](https://github.com/coze-dev/coze-js/blob/main/LICENSE)
6
+ [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
7
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg)](https://github.com/coze-dev/coze-js/pulls)
8
+
3
9
  A powerful real-time communication SDK for voice interactions with Coze AI bots.
4
10
 
5
11
  ## Features
@@ -1,7 +1,29 @@
1
1
  /*! For license information please see index.cjs.LICENSE.txt */
2
2
  "use strict";
3
- // The require scope
4
- var __webpack_require__ = {};
3
+ var __webpack_modules__ = {
4
+ "?de24": function() {
5
+ /* (ignored) */ },
6
+ "?2a9f": function() {
7
+ /* (ignored) */ },
8
+ "?d039": function() {
9
+ /* (ignored) */ }
10
+ };
11
+ /************************************************************************/ // The module cache
12
+ var __webpack_module_cache__ = {};
13
+ // The require function
14
+ function __webpack_require__(moduleId) {
15
+ // Check if module is in cache
16
+ var cachedModule = __webpack_module_cache__[moduleId];
17
+ if (void 0 !== cachedModule) return cachedModule.exports;
18
+ // Create a new module (and put it into the cache)
19
+ var module = __webpack_module_cache__[moduleId] = {
20
+ exports: {}
21
+ };
22
+ // Execute the module function
23
+ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
24
+ // Return the exports of the module
25
+ return module.exports;
26
+ }
5
27
  /************************************************************************/ // webpack/runtime/define_property_getters
6
28
  (()=>{
7
29
  __webpack_require__.d = function(exports1, definition) {
@@ -1062,14 +1084,14 @@ const _navigator = 'object' == typeof navigator && navigator || void 0;
1062
1084
  */ const hasStandardBrowserWebWorkerEnv = (()=>'undefined' != typeof WorkerGlobalScope && // eslint-disable-next-line no-undef
1063
1085
  self instanceof WorkerGlobalScope && 'function' == typeof self.importScripts)();
1064
1086
  const origin = hasBrowserEnv && window.location.href || 'http://localhost';
1065
- /* ESM default export */ const platform = {
1087
+ /* ESM default export */ const lib_platform = {
1066
1088
  ...common_utils_namespaceObject,
1067
1089
  ...browser
1068
1090
  };
1069
1091
  function toURLEncodedForm(data, options) {
1070
- return toFormData(data, new platform.classes.URLSearchParams(), Object.assign({
1092
+ return toFormData(data, new lib_platform.classes.URLSearchParams(), Object.assign({
1071
1093
  visitor: function(value, key, path, helpers) {
1072
- if (platform.isNode && utils.isBuffer(value)) {
1094
+ if (lib_platform.isNode && utils.isBuffer(value)) {
1073
1095
  this.append(key, value.toString('base64'));
1074
1096
  return false;
1075
1097
  }
@@ -1230,8 +1252,8 @@ const defaults_defaults = {
1230
1252
  maxContentLength: -1,
1231
1253
  maxBodyLength: -1,
1232
1254
  env: {
1233
- FormData: platform.classes.FormData,
1234
- Blob: platform.classes.Blob
1255
+ FormData: lib_platform.classes.FormData,
1256
+ Blob: lib_platform.classes.Blob
1235
1257
  },
1236
1258
  validateStatus: function(status) {
1237
1259
  return status >= 200 && status < 300;
@@ -1665,10 +1687,10 @@ const progressEventDecorator = (total, throttled)=>{
1665
1687
  ];
1666
1688
  };
1667
1689
  const asyncDecorator = (fn)=>(...args)=>utils.asap(()=>fn(...args));
1668
- /* ESM default export */ const helpers_isURLSameOrigin = platform.hasStandardBrowserEnv ? // Standard browser envs have full support of the APIs needed to test
1690
+ /* ESM default export */ const helpers_isURLSameOrigin = lib_platform.hasStandardBrowserEnv ? // Standard browser envs have full support of the APIs needed to test
1669
1691
  // whether the request URL is of the same origin as current location.
1670
1692
  function() {
1671
- const msie = platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent);
1693
+ const msie = lib_platform.navigator && /(msie|trident)/i.test(lib_platform.navigator.userAgent);
1672
1694
  const urlParsingNode = document.createElement('a');
1673
1695
  let originURL;
1674
1696
  /**
@@ -1712,7 +1734,7 @@ function() {
1712
1734
  return true;
1713
1735
  };
1714
1736
  }();
1715
- /* ESM default export */ const cookies = platform.hasStandardBrowserEnv ? // Standard browser envs support document.cookie
1737
+ /* ESM default export */ const cookies = lib_platform.hasStandardBrowserEnv ? // Standard browser envs support document.cookie
1716
1738
  {
1717
1739
  write (name, value, expires, path, domain, secure) {
1718
1740
  const cookie = [
@@ -1863,7 +1885,7 @@ const headersToObject = (thing)=>thing instanceof AxiosHeaders ? {
1863
1885
  if (auth) headers.set('Authorization', 'Basic ' + btoa((auth.username || '') + ':' + (auth.password ? unescape(encodeURIComponent(auth.password)) : '')));
1864
1886
  let contentType;
1865
1887
  if (utils.isFormData(data)) {
1866
- if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) headers.setContentType(void 0); // Let the browser set it
1888
+ if (lib_platform.hasStandardBrowserEnv || lib_platform.hasStandardBrowserWebWorkerEnv) headers.setContentType(void 0); // Let the browser set it
1867
1889
  else if (false !== (contentType = headers.getContentType())) {
1868
1890
  // fix semicolon duplication issue for ReactNative FormData implementation
1869
1891
  const [type, ...tokens] = contentType ? contentType.split(';').map((token)=>token.trim()).filter(Boolean) : [];
@@ -1876,7 +1898,7 @@ const headersToObject = (thing)=>thing instanceof AxiosHeaders ? {
1876
1898
  // Add xsrf header
1877
1899
  // This is only done if running in a standard browser environment.
1878
1900
  // Specifically not if we're in a web worker, or react-native.
1879
- if (platform.hasStandardBrowserEnv) {
1901
+ if (lib_platform.hasStandardBrowserEnv) {
1880
1902
  withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig));
1881
1903
  if (withXSRFToken || false !== withXSRFToken && helpers_isURLSameOrigin(newConfig.url)) {
1882
1904
  // Add xsrf header
@@ -2001,7 +2023,7 @@ const isXHRAdapterSupported = 'undefined' != typeof XMLHttpRequest;
2001
2023
  if (_config.signal) _config.signal.aborted ? onCanceled() : _config.signal.addEventListener('abort', onCanceled);
2002
2024
  }
2003
2025
  const protocol = parseProtocol(_config.url);
2004
- if (protocol && -1 === platform.protocols.indexOf(protocol)) {
2026
+ if (protocol && -1 === lib_platform.protocols.indexOf(protocol)) {
2005
2027
  reject(new core_AxiosError('Unsupported protocol ' + protocol + ':', core_AxiosError.ERR_BAD_REQUEST, config));
2006
2028
  return;
2007
2029
  }
@@ -2127,7 +2149,7 @@ const test = (fn, ...args)=>{
2127
2149
  };
2128
2150
  const supportsRequestStream = isReadableStreamSupported && test(()=>{
2129
2151
  let duplexAccessed = false;
2130
- const hasContentType = new Request(platform.origin, {
2152
+ const hasContentType = new Request(lib_platform.origin, {
2131
2153
  body: new ReadableStream(),
2132
2154
  method: 'POST',
2133
2155
  get duplex () {
@@ -2159,7 +2181,7 @@ const getBodyLength = async (body)=>{
2159
2181
  if (null == body) return 0;
2160
2182
  if (utils.isBlob(body)) return body.size;
2161
2183
  if (utils.isSpecCompliantForm(body)) {
2162
- const _request = new Request(platform.origin, {
2184
+ const _request = new Request(lib_platform.origin, {
2163
2185
  method: 'POST',
2164
2186
  body
2165
2187
  });
@@ -2834,26 +2856,12 @@ axios.default = axios;
2834
2856
  // Keep top-level export same with static properties
2835
2857
  // so that it can keep same with es module or cjs
2836
2858
  const { Axios: axios_Axios, AxiosError: axios_AxiosError, CanceledError: axios_CanceledError, isCancel: axios_isCancel, CancelToken: axios_CancelToken, VERSION: axios_VERSION, all: axios_all, Cancel, isAxiosError: axios_isAxiosError, spread: axios_spread, toFormData: axios_toFormData, AxiosHeaders: axios_AxiosHeaders, HttpStatusCode: axios_HttpStatusCode, formToJSON, getAdapter, mergeConfig: axios_mergeConfig } = lib_axios;
2837
- var __webpack_modules__ = {
2838
- "?6728": function() {
2839
- /* (ignored) */ }
2840
- };
2841
- /************************************************************************/ // The module cache
2842
- var __webpack_module_cache__ = {};
2843
- // The require function
2844
- function __nested_webpack_require_293__(moduleId) {
2845
- // Check if module is in cache
2846
- var cachedModule = __webpack_module_cache__[moduleId];
2847
- if (void 0 !== cachedModule) return cachedModule.exports;
2848
- // Create a new module (and put it into the cache)
2849
- var module = __webpack_module_cache__[moduleId] = {
2850
- exports: {}
2851
- };
2852
- // Execute the module function
2853
- __webpack_modules__[moduleId](module, module.exports, __nested_webpack_require_293__);
2854
- // Return the exports of the module
2855
- return module.exports;
2856
- } /************************************************************************/
2859
+ // EXTERNAL MODULE: os (ignored)
2860
+ var os_ignored_ = __webpack_require__("?d039");
2861
+ // EXTERNAL MODULE: crypto (ignored)
2862
+ __webpack_require__("?de24");
2863
+ // EXTERNAL MODULE: jsonwebtoken (ignored)
2864
+ __webpack_require__("?2a9f");
2857
2865
  class APIResource {
2858
2866
  constructor(client){
2859
2867
  this._client = client;
@@ -3616,6 +3624,56 @@ class esm_Audio extends APIResource {
3616
3624
  super(...args), this.rooms = new Rooms(this._client), this.voices = new Voices(this._client), this.speech = new Speech(this._client);
3617
3625
  }
3618
3626
  }
3627
+ var package_namespaceObject = JSON.parse('{"name":"@coze/api","version":"1.0.11","description":"Official Coze Node.js SDK for seamless AI integration into your applications | 扣子官方 Node.js SDK,助您轻松集成 AI 能力到应用中","keywords":["coze","ai","nodejs","sdk","chatbot","typescript"],"homepage":"https://github.com/coze-dev/coze-js/tree/main/packages/coze-js","bugs":{"url":"https://github.com/coze-dev/coze-js/issues"},"repository":{"type":"git","url":"https://github.com/coze-dev/coze-js.git","directory":"packages/coze-js"},"license":"MIT","author":"Leeight <leeight@gmail.com>","type":"module","exports":{".":{"require":"./dist/cjs/index.cjs","import":"./dist/esm/index.js","types":"./dist/types/index.d.ts"}},"main":"dist/cjs/index.cjs","module":"dist/esm/index.js","browser":{"crypto":false,"os":false,"jsonwebtoken":false},"types":"dist/types/index.d.ts","files":["dist","LICENSE","README.md","!**/*.tsbuildinfo"],"scripts":{"build":"rm -rf dist && rslib build","format":"prettier --write .","lint":"eslint ./ --cache --quiet","prepublishOnly":"npm run build","start":"rm -rf dist && rslib build -w","test":"vitest","test:cov":"vitest --coverage --run"},"dependencies":{"jsonwebtoken":"^9.0.2"},"devDependencies":{"@coze-infra/eslint-config":"workspace:*","@coze-infra/ts-config":"workspace:*","@coze-infra/vitest-config":"workspace:*","@rslib/core":"0.0.18","@swc/core":"^1.3.14","@types/jsonwebtoken":"^9.0.0","@types/node":"^20","@types/uuid":"^9.0.1","@types/whatwg-fetch":"^0.0.33","@vitest/coverage-v8":"~2.1.4","axios":"^1.7.7","typescript":"^5.5.3","vitest":"~2.1.4"},"peerDependencies":{"axios":"^1.7.1"}}'); // CONCATENATED MODULE: ./src/version.ts
3628
+ const { version: esm_version } = package_namespaceObject;
3629
+ const getEnv = ()=>{
3630
+ const nodeVersion = process.version.slice(1); // Remove 'v' prefix
3631
+ const { platform } = process;
3632
+ let osName = platform.toLowerCase();
3633
+ let osVersion = os_ignored_.release();
3634
+ if ('darwin' === platform) {
3635
+ osName = 'macos';
3636
+ // Try to parse the macOS version
3637
+ try {
3638
+ const darwinVersion = os_ignored_.release().split('.');
3639
+ if (darwinVersion.length >= 2) {
3640
+ const majorVersion = parseInt(darwinVersion[0], 10);
3641
+ if (!isNaN(majorVersion) && majorVersion >= 9) {
3642
+ const macVersion = majorVersion - 9;
3643
+ osVersion = `10.${macVersion}.${darwinVersion[1]}`;
3644
+ }
3645
+ }
3646
+ } catch (error) {
3647
+ // Keep the default os.release() value if parsing fails
3648
+ }
3649
+ } else if ('win32' === platform) {
3650
+ osName = 'windows';
3651
+ osVersion = os_ignored_.release();
3652
+ } else if ('linux' === platform) {
3653
+ osName = 'linux';
3654
+ osVersion = os_ignored_.release();
3655
+ }
3656
+ return {
3657
+ osName,
3658
+ osVersion,
3659
+ nodeVersion
3660
+ };
3661
+ };
3662
+ const getUserAgent = ()=>{
3663
+ const { nodeVersion, osName, osVersion } = getEnv();
3664
+ return `coze-js/${esm_version} node/${nodeVersion} ${osName}/${osVersion}`.toLowerCase();
3665
+ };
3666
+ const getNodeClientUserAgent = ()=>{
3667
+ const { osVersion, nodeVersion, osName } = getEnv();
3668
+ const ua = {
3669
+ version: esm_version,
3670
+ lang: 'node',
3671
+ lang_version: nodeVersion,
3672
+ os_name: osName,
3673
+ os_version: osVersion
3674
+ };
3675
+ return JSON.stringify(ua);
3676
+ };
3619
3677
  /* eslint-disable @typescript-eslint/no-explicit-any */ const esm_handleError = (error)=>{
3620
3678
  if (!error.isAxiosError && (!error.code || !error.message)) return new CozeError(`Unexpected error: ${error.message}`);
3621
3679
  if ('ECONNABORTED' === error.code && error.message.includes('timeout') || 'ETIMEDOUT' === error.code) {
@@ -3688,10 +3746,10 @@ async function fetchAPI(url) {
3688
3746
  const headers = {
3689
3747
  authorization: `Bearer ${this.token}`
3690
3748
  };
3691
- // FIXME: browser 下存在跨域问题,后续再看看
3692
- // if (!isBrowser()) {
3693
- // headers['agw-js-conv'] = 'str';
3694
- // }
3749
+ if (!isBrowser()) {
3750
+ headers['User-Agent'] = getUserAgent();
3751
+ headers['X-Coze-Client-User-Agent'] = getNodeClientUserAgent();
3752
+ }
3695
3753
  const config = esm_mergeConfig(this.axiosOptions, options, {
3696
3754
  headers
3697
3755
  });
@@ -3772,8 +3830,6 @@ APIClient.InternalServerError = InternalServerError;
3772
3830
  APIClient.GatewayError = GatewayError;
3773
3831
  APIClient.TimeoutError = TimeoutError;
3774
3832
  APIClient.UserAbortError = APIUserAbortError;
3775
- // EXTERNAL MODULE: crypto (ignored)
3776
- __nested_webpack_require_293__("?6728");
3777
3833
  class CozeAPI extends APIClient {
3778
3834
  constructor(...args){
3779
3835
  super(...args), this.bots = new Bots(this), this.chat = new Chat(this), this.conversations = new Conversations(this), this.files = new Files(this), this.knowledge = new Knowledge(this), this.workflows = new Workflows(this), this.workspaces = new WorkSpaces(this), this.audio = new esm_Audio(this);
@@ -38167,10 +38223,19 @@ var VERTC = _createClass(function e() {
38167
38223
  };
38168
38224
  /**
38169
38225
  * Check microphone permission,return boolean
38170
- */ const checkPermission = async ()=>(await index_esm_min_index.enableDevices({
38171
- audio: true,
38172
- video: false
38173
- })).audio;
38226
+ */ const checkPermission = async function() {
38227
+ let { audio = true, video = false } = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
38228
+ try {
38229
+ const result = await index_esm_min_index.enableDevices({
38230
+ audio,
38231
+ video
38232
+ });
38233
+ return result.audio;
38234
+ } catch (error) {
38235
+ console.error('Failed to check device permissions:', error);
38236
+ return false;
38237
+ }
38238
+ };
38174
38239
  /**
38175
38240
  * Get audio devices
38176
38241
  * @returns Promise<AudioDevices> Object containing arrays of audio input and output devices
@@ -38178,11 +38243,15 @@ var VERTC = _createClass(function e() {
38178
38243
  const devices = await index_esm_min_index.enumerateDevices();
38179
38244
  if (!(null == devices ? void 0 : devices.length)) return {
38180
38245
  audioInputs: [],
38181
- audioOutputs: []
38246
+ audioOutputs: [],
38247
+ videoInputs: [],
38248
+ videoOutputs: []
38182
38249
  };
38183
38250
  return {
38184
38251
  audioInputs: devices.filter((i)=>i.deviceId && 'audioinput' === i.kind),
38185
- audioOutputs: devices.filter((i)=>i.deviceId && 'audiooutput' === i.kind)
38252
+ audioOutputs: devices.filter((i)=>i.deviceId && 'audiooutput' === i.kind),
38253
+ videoInputs: devices.filter((i)=>i.deviceId && 'videoinput' === i.kind),
38254
+ videoOutputs: devices.filter((i)=>i.deviceId && 'videooutput' === i.kind)
38186
38255
  };
38187
38256
  };
38188
38257
  var error_RealtimeError = /*#__PURE__*/ function(RealtimeError) {
@@ -38196,12 +38265,20 @@ var error_RealtimeError = /*#__PURE__*/ function(RealtimeError) {
38196
38265
  RealtimeError["NETWORK_ERROR"] = "NETWORK_ERROR";
38197
38266
  RealtimeError["INVALID_STATE"] = "INVALID_STATE";
38198
38267
  RealtimeError["CREATE_ROOM_ERROR"] = "CREATE_ROOM_ERROR";
38268
+ RealtimeError["PARSE_MESSAGE_ERROR"] = "PARSE_MESSAGE_ERROR";
38269
+ RealtimeError["HANDLER_MESSAGE_ERROR"] = "HANDLER_MESSAGE_ERROR";
38199
38270
  return RealtimeError;
38200
38271
  }({});
38201
38272
  class RealtimeAPIError extends Error {
38202
- constructor(code, message){
38203
- super(`[${code}] ${message}`), this.code = code;
38273
+ /**
38274
+ * @param code - Error code
38275
+ * @param message - Error message
38276
+ * @param error - Error object
38277
+ */ constructor(code, message, error){
38278
+ super(`[${code}] ${message}`);
38204
38279
  this.name = 'RealtimeAPIError';
38280
+ this.code = code;
38281
+ this.error = error;
38205
38282
  }
38206
38283
  }
38207
38284
  var event_handler_EventNames = /*#__PURE__*/ function(EventNames) {
@@ -38238,6 +38315,18 @@ var event_handler_EventNames = /*#__PURE__*/ function(EventNames) {
38238
38315
  * zh: 客户端音频静音
38239
38316
  */ EventNames["AUDIO_MUTED"] = "client.audio.muted";
38240
38317
  /**
38318
+ * en: Client video on
38319
+ * zh: 客户端视频开启
38320
+ */ EventNames["VIDEO_ON"] = "client.video.on";
38321
+ /**
38322
+ * en: Client video off
38323
+ * zh: 客户端视频关闭
38324
+ */ EventNames["VIDEO_OFF"] = "client.video.off";
38325
+ /**
38326
+ * en: Client video event
38327
+ * zh: 客户端视频事件
38328
+ */ EventNames["PLAYER_EVENT"] = "client.video.event";
38329
+ /**
38241
38330
  * en: Client error
38242
38331
  * zh: 客户端错误
38243
38332
  */ EventNames["ERROR"] = "client.error";
@@ -38257,6 +38346,14 @@ var event_handler_EventNames = /*#__PURE__*/ function(EventNames) {
38257
38346
  * en: Audio output device changed
38258
38347
  * zh: 音频输出设备改变
38259
38348
  */ EventNames["AUDIO_OUTPUT_DEVICE_CHANGED"] = "client.output.device.changed";
38349
+ /**
38350
+ * en: Bot joined
38351
+ * zh: Bot 加入
38352
+ */ EventNames["BOT_JOIN"] = "server.bot.join";
38353
+ /**
38354
+ * en: Bot left
38355
+ * zh: Bot 离开
38356
+ */ EventNames["BOT_LEAVE"] = "server.bot.leave";
38260
38357
  return EventNames;
38261
38358
  }({});
38262
38359
  class RealtimeEventHandler {
@@ -38280,7 +38377,11 @@ class RealtimeEventHandler {
38280
38377
  }
38281
38378
  // eslint-disable-next-line max-params
38282
38379
  _dispatchToHandlers(eventName, event, handlers, prefix) {
38283
- for (const handler of handlers)if (!prefix || eventName.startsWith(prefix)) handler(eventName, event);
38380
+ for (const handler of handlers)if (!prefix || eventName.startsWith(prefix)) try {
38381
+ handler(eventName, event);
38382
+ } catch (e) {
38383
+ throw new RealtimeAPIError(error_RealtimeError.HANDLER_MESSAGE_ERROR, `Failed to handle message: ${eventName}`);
38384
+ }
38284
38385
  }
38285
38386
  dispatch(eventName, event) {
38286
38387
  this._log(`dispatch ${eventName} event`);
@@ -41552,6 +41653,7 @@ class EngineClient extends RealtimeEventHandler {
41552
41653
  this.engine.on(index_esm_min_index.events.onUserJoined, this.handleUserJoin);
41553
41654
  this.engine.on(index_esm_min_index.events.onUserLeave, this.handleUserLeave);
41554
41655
  this.engine.on(index_esm_min_index.events.onError, this.handleEventError);
41656
+ this.engine.on(index_esm_min_index.events.onPlayerEvent, this.handlePlayerEvent);
41555
41657
  if (this._debug) {
41556
41658
  this.engine.on(index_esm_min_index.events.onLocalAudioPropertiesReport, this.handleLocalAudioPropertiesReport);
41557
41659
  this.engine.on(index_esm_min_index.events.onRemoteAudioPropertiesReport, this.handleRemoteAudioPropertiesReport);
@@ -41562,45 +41664,62 @@ class EngineClient extends RealtimeEventHandler {
41562
41664
  this.engine.off(index_esm_min_index.events.onUserJoined, this.handleUserJoin);
41563
41665
  this.engine.off(index_esm_min_index.events.onUserLeave, this.handleUserLeave);
41564
41666
  this.engine.off(index_esm_min_index.events.onError, this.handleEventError);
41667
+ this.engine.off(index_esm_min_index.events.onPlayerEvent, this.handlePlayerEvent);
41565
41668
  if (this._debug) {
41566
41669
  this.engine.off(index_esm_min_index.events.onLocalAudioPropertiesReport, this.handleLocalAudioPropertiesReport);
41567
41670
  this.engine.off(index_esm_min_index.events.onRemoteAudioPropertiesReport, this.handleRemoteAudioPropertiesReport);
41568
41671
  }
41569
41672
  }
41673
+ _parseMessage(event) {
41674
+ try {
41675
+ return JSON.parse(event.message);
41676
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41677
+ } catch (e) {
41678
+ throw new RealtimeAPIError(error_RealtimeError.PARSE_MESSAGE_ERROR, (null == e ? void 0 : e.message) || 'Unknown error');
41679
+ }
41680
+ }
41570
41681
  handleMessage(event) {
41571
41682
  try {
41572
- const message = JSON.parse(event.message);
41683
+ const message = this._parseMessage(event);
41573
41684
  this.dispatch(`server.${message.event_type}`, message);
41574
41685
  } catch (e) {
41575
- this.dispatch('client.error', {
41576
- message: `Failed to parse message: ${event.message}`,
41577
- error: e
41578
- });
41686
+ if (e instanceof RealtimeAPIError) {
41687
+ if (e.code === error_RealtimeError.PARSE_MESSAGE_ERROR) this.dispatch(event_handler_EventNames.ERROR, {
41688
+ message: `Failed to parse message: ${event.message}`,
41689
+ error: e
41690
+ });
41691
+ else if (e.code === error_RealtimeError.HANDLER_MESSAGE_ERROR) this.dispatch(event_handler_EventNames.ERROR, {
41692
+ message: `Failed to handle message: ${event.message}`,
41693
+ error: e
41694
+ });
41695
+ } else this.dispatch(event_handler_EventNames.ERROR, e);
41579
41696
  }
41580
41697
  }
41581
41698
  handleEventError(e) {
41582
- this.dispatch('client.error', e);
41699
+ this.dispatch(event_handler_EventNames.ERROR, e);
41583
41700
  }
41584
41701
  handleUserJoin(event) {
41585
41702
  this.joinUserId = event.userInfo.userId;
41586
- this.dispatch('server.bot.join', event);
41703
+ this.dispatch(event_handler_EventNames.BOT_JOIN, event);
41587
41704
  }
41588
41705
  handleUserLeave(event) {
41589
- this.dispatch('server.bot.leave', event);
41706
+ this.dispatch(event_handler_EventNames.BOT_LEAVE, event);
41707
+ }
41708
+ handlePlayerEvent(event) {
41709
+ this.dispatch(event_handler_EventNames.PLAYER_EVENT, event);
41590
41710
  }
41591
41711
  async joinRoom(options) {
41592
- const { token, roomId, uid, audioMutedDefault = false } = options;
41712
+ const { token, roomId, uid, audioMutedDefault, videoOnDefault } = options;
41593
41713
  try {
41594
41714
  await this.engine.joinRoom(token, roomId, {
41595
41715
  userId: uid
41596
41716
  }, {
41597
41717
  isAutoPublish: !audioMutedDefault,
41598
41718
  isAutoSubscribeAudio: true,
41599
- isAutoSubscribeVideo: false
41719
+ isAutoSubscribeVideo: this._isSupportVideo && videoOnDefault
41600
41720
  });
41601
41721
  } catch (e) {
41602
41722
  if (e instanceof Error) throw new RealtimeAPIError(error_RealtimeError.CONNECTION_ERROR, e.message);
41603
- throw new RealtimeAPIError(error_RealtimeError.CONNECTION_ERROR, 'Unknown error');
41604
41723
  }
41605
41724
  }
41606
41725
  async setAudioInputDevice(deviceId) {
@@ -41614,19 +41733,26 @@ class EngineClient extends RealtimeEventHandler {
41614
41733
  if (-1 === devices.audioOutputs.findIndex((i)=>i.deviceId === deviceId)) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, `Audio output device not found: ${deviceId}`);
41615
41734
  await this.engine.setAudioPlaybackDevice(deviceId);
41616
41735
  }
41617
- async createLocalStream() {
41736
+ async createLocalStream(userId, videoConfig) {
41618
41737
  const devices = await getAudioDevices();
41619
41738
  if (!devices.audioInputs.length) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, 'Failed to get devices');
41739
+ if (this._isSupportVideo && !devices.videoInputs.length) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, 'Failed to get devices');
41620
41740
  await this.engine.startAudioCapture(devices.audioInputs[0].deviceId);
41741
+ if (this._isSupportVideo && (null == videoConfig ? void 0 : videoConfig.videoOnDefault)) await this.engine.startVideoCapture(devices.videoInputs[0].deviceId);
41742
+ if (this._isSupportVideo) this.engine.setLocalVideoPlayer(StreamIndex$1.STREAM_INDEX_MAIN, {
41743
+ renderDom: (null == videoConfig ? void 0 : videoConfig.renderDom) || 'local-player',
41744
+ userId
41745
+ });
41621
41746
  }
41622
41747
  async disconnect() {
41623
41748
  try {
41749
+ if (this._isSupportVideo) await this.engine.stopVideoCapture();
41624
41750
  await this.engine.stopAudioCapture();
41625
41751
  await this.engine.unpublishStream(MediaType$1.AUDIO);
41626
41752
  await this.engine.leaveRoom();
41627
41753
  this.removeEventListener();
41628
41754
  } catch (e) {
41629
- this.dispatch('client.error', e);
41755
+ this.dispatch(event_handler_EventNames.ERROR, e);
41630
41756
  throw e;
41631
41757
  }
41632
41758
  }
@@ -41635,7 +41761,16 @@ class EngineClient extends RealtimeEventHandler {
41635
41761
  if (isMicOn) await this.engine.publishStream(MediaType$1.AUDIO);
41636
41762
  else await this.engine.unpublishStream(MediaType$1.AUDIO);
41637
41763
  } catch (e) {
41638
- this.dispatch('client.error', e);
41764
+ this.dispatch(event_handler_EventNames.ERROR, e);
41765
+ throw e;
41766
+ }
41767
+ }
41768
+ async changeVideoState(isVideoOn) {
41769
+ try {
41770
+ if (isVideoOn) await this.engine.startVideoCapture();
41771
+ else await this.engine.stopVideoCapture();
41772
+ } catch (e) {
41773
+ this.dispatch(event_handler_EventNames.ERROR, e);
41639
41774
  throw e;
41640
41775
  }
41641
41776
  }
@@ -41648,7 +41783,7 @@ class EngineClient extends RealtimeEventHandler {
41648
41783
  }));
41649
41784
  this._log(`interrupt ${this.joinUserId} ${result}`);
41650
41785
  } catch (e) {
41651
- this.dispatch('client.error', e);
41786
+ this.dispatch(event_handler_EventNames.ERROR, e);
41652
41787
  throw e;
41653
41788
  }
41654
41789
  }
@@ -41657,7 +41792,7 @@ class EngineClient extends RealtimeEventHandler {
41657
41792
  const result = await this.engine.sendUserMessage(this.joinUserId, JSON.stringify(message));
41658
41793
  this._log(`sendMessage ${this.joinUserId} ${JSON.stringify(message)} ${result}`);
41659
41794
  } catch (e) {
41660
- this.dispatch('client.error', e);
41795
+ this.dispatch(event_handler_EventNames.ERROR, e);
41661
41796
  throw e;
41662
41797
  }
41663
41798
  }
@@ -41698,7 +41833,7 @@ class EngineClient extends RealtimeEventHandler {
41698
41833
  try {
41699
41834
  await this.engine.startAudioPlaybackDeviceTest('audio-test.wav', 200);
41700
41835
  } catch (e) {
41701
- this.dispatch('client.error', e);
41836
+ this.dispatch(event_handler_EventNames.ERROR, e);
41702
41837
  throw e;
41703
41838
  }
41704
41839
  }
@@ -41706,12 +41841,13 @@ class EngineClient extends RealtimeEventHandler {
41706
41841
  try {
41707
41842
  this.engine.stopAudioPlaybackDeviceTest();
41708
41843
  } catch (e) {
41709
- this.dispatch('client.error', e);
41844
+ this.dispatch(event_handler_EventNames.ERROR, e);
41710
41845
  throw e;
41711
41846
  }
41712
41847
  }
41713
- constructor(appId, debug = false, isTestEnv = false){
41714
- super(debug), this.joinUserId = '', this._AIAnsExtension = null;
41848
+ // eslint-disable-next-line max-params
41849
+ constructor(appId, debug = false, isTestEnv = false, isSupportVideo = false){
41850
+ super(debug), this.joinUserId = '', this._AIAnsExtension = null, this._isSupportVideo = false;
41715
41851
  if (isTestEnv) index_esm_min_index.setParameter('ICE_CONFIG_REQUEST_URLS', [
41716
41852
  'rtc-test.bytedance.com'
41717
41853
  ]);
@@ -41720,9 +41856,11 @@ class EngineClient extends RealtimeEventHandler {
41720
41856
  this.handleUserJoin = this.handleUserJoin.bind(this);
41721
41857
  this.handleUserLeave = this.handleUserLeave.bind(this);
41722
41858
  this.handleEventError = this.handleEventError.bind(this);
41859
+ this.handlePlayerEvent = this.handlePlayerEvent.bind(this);
41723
41860
  // Debug only
41724
41861
  this.handleLocalAudioPropertiesReport = this.handleLocalAudioPropertiesReport.bind(this);
41725
41862
  this.handleRemoteAudioPropertiesReport = this.handleRemoteAudioPropertiesReport.bind(this);
41863
+ this._isSupportVideo = isSupportVideo;
41726
41864
  }
41727
41865
  }
41728
41866
  class RealtimeClient extends RealtimeEventHandler {
@@ -41731,6 +41869,7 @@ class RealtimeClient extends RealtimeEventHandler {
41731
41869
  *
41732
41870
  * zh: 建立与 Coze API 的连接并加入房间
41733
41871
  */ async connect() {
41872
+ var _this__config_videoConfig;
41734
41873
  const { botId, conversationId, voiceId } = this._config;
41735
41874
  let roomInfo;
41736
41875
  try {
@@ -41743,11 +41882,10 @@ class RealtimeClient extends RealtimeEventHandler {
41743
41882
  });
41744
41883
  } catch (error) {
41745
41884
  this.dispatch(event_handler_EventNames.ERROR, error);
41746
- throw new RealtimeAPIError(error_RealtimeError.CREATE_ROOM_ERROR, error instanceof Error ? error.message : 'Unknown error');
41885
+ throw new RealtimeAPIError(error_RealtimeError.CREATE_ROOM_ERROR, error instanceof Error ? error.message : 'Unknown error', error);
41747
41886
  }
41748
- this._roomInfo = roomInfo;
41749
41887
  // Step2 create engine
41750
- this._client = new EngineClient(roomInfo.app_id, this._config.debug, this._isTestEnv);
41888
+ this._client = new EngineClient(roomInfo.app_id, this._config.debug, this._isTestEnv, this._isSupportVideo);
41751
41889
  // Step3 bind engine events
41752
41890
  this._client.bindEngineEvents();
41753
41891
  this._client.on(event_handler_EventNames.ALL, (eventName, data)=>{
@@ -41762,16 +41900,17 @@ class RealtimeClient extends RealtimeEventHandler {
41762
41900
  this._client.changeAIAnsExtension(true);
41763
41901
  this.dispatch(event_handler_EventNames.SUPPRESS_NON_STATIONARY_NOISE, {});
41764
41902
  }
41765
- var _this__config_audioMutedDefault;
41903
+ var _this__config_audioMutedDefault, _this__config_videoConfig_videoOnDefault;
41766
41904
  // Step4 join room
41767
41905
  await this._client.joinRoom({
41768
41906
  token: roomInfo.token,
41769
41907
  roomId: roomInfo.room_id,
41770
41908
  uid: roomInfo.uid,
41771
- audioMutedDefault: null !== (_this__config_audioMutedDefault = this._config.audioMutedDefault) && void 0 !== _this__config_audioMutedDefault && _this__config_audioMutedDefault
41909
+ audioMutedDefault: null !== (_this__config_audioMutedDefault = this._config.audioMutedDefault) && void 0 !== _this__config_audioMutedDefault && _this__config_audioMutedDefault,
41910
+ videoOnDefault: null === (_this__config_videoConfig_videoOnDefault = null === (_this__config_videoConfig = this._config.videoConfig) || void 0 === _this__config_videoConfig ? void 0 : _this__config_videoConfig.videoOnDefault) || void 0 === _this__config_videoConfig_videoOnDefault || _this__config_videoConfig_videoOnDefault
41772
41911
  });
41773
41912
  // Step5 create local stream
41774
- await this._client.createLocalStream();
41913
+ await this._client.createLocalStream(roomInfo.uid, this._config.videoConfig);
41775
41914
  // step6 set connected and dispatch connected event
41776
41915
  this.isConnected = true;
41777
41916
  this.dispatch(event_handler_EventNames.CONNECTED, {
@@ -41822,6 +41961,12 @@ class RealtimeClient extends RealtimeEventHandler {
41822
41961
  if (isEnable) this.dispatch(event_handler_EventNames.AUDIO_UNMUTED, {});
41823
41962
  else this.dispatch(event_handler_EventNames.AUDIO_MUTED, {});
41824
41963
  }
41964
+ async setVideoEnable(isEnable) {
41965
+ var _this__client;
41966
+ await (null === (_this__client = this._client) || void 0 === _this__client ? void 0 : _this__client.changeVideoState(isEnable));
41967
+ if (isEnable) this.dispatch(event_handler_EventNames.VIDEO_ON, {});
41968
+ else this.dispatch(event_handler_EventNames.VIDEO_OFF, {});
41969
+ }
41825
41970
  /**
41826
41971
  * en: Enable audio properties reporting (debug mode only)
41827
41972
  *
@@ -41907,7 +42052,7 @@ class RealtimeClient extends RealtimeEventHandler {
41907
42052
  * @param config.suppressNonStationaryNoise - Optional, suppress non-stationary noise, defaults to false. |
41908
42053
  * 可选,默认是否抑制非静态噪声,默认值为 false。
41909
42054
  */ constructor(config){
41910
- super(config.debug), this._client = null, this._roomInfo = null, this.isConnected = false, this._isTestEnv = false;
42055
+ super(config.debug), this._client = null, this.isConnected = false, this._isTestEnv = false, this._isSupportVideo = false;
41911
42056
  this._config = config;
41912
42057
  var _this__config_baseURL;
41913
42058
  const defaultBaseURL = null !== (_this__config_baseURL = this._config.baseURL) && void 0 !== _this__config_baseURL ? _this__config_baseURL : 'https://api.coze.cn';
@@ -41919,6 +42064,7 @@ class RealtimeClient extends RealtimeEventHandler {
41919
42064
  allowPersonalAccessTokenInBrowser: this._config.allowPersonalAccessTokenInBrowser
41920
42065
  });
41921
42066
  this._isTestEnv = 'https://api.coze.cn' !== defaultBaseURL;
42067
+ this._isSupportVideo = !!config.videoConfig;
41922
42068
  }
41923
42069
  }
41924
42070
  var __webpack_export_target__ = exports;