@coze/realtime-api 0.0.4 → 1.0.0

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/dist/esm/index.js CHANGED
@@ -1,6 +1,28 @@
1
1
  /*! For license information please see index.js.LICENSE.txt */
2
- // The require scope
3
- var __webpack_require__ = {};
2
+ var __webpack_modules__ = {
3
+ "?d7f0": function() {
4
+ /* (ignored) */ },
5
+ "?fcd3": function() {
6
+ /* (ignored) */ },
7
+ "?d2d5": function() {
8
+ /* (ignored) */ }
9
+ };
10
+ /************************************************************************/ // The module cache
11
+ var __webpack_module_cache__ = {};
12
+ // The require function
13
+ function __webpack_require__(moduleId) {
14
+ // Check if module is in cache
15
+ var cachedModule = __webpack_module_cache__[moduleId];
16
+ if (void 0 !== cachedModule) return cachedModule.exports;
17
+ // Create a new module (and put it into the cache)
18
+ var module = __webpack_module_cache__[moduleId] = {
19
+ exports: {}
20
+ };
21
+ // Execute the module function
22
+ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
23
+ // Return the exports of the module
24
+ return module.exports;
25
+ }
4
26
  /************************************************************************/ // webpack/runtime/define_property_getters
5
27
  (()=>{
6
28
  __webpack_require__.d = function(exports, definition) {
@@ -1050,14 +1072,14 @@ const _navigator = 'object' == typeof navigator && navigator || void 0;
1050
1072
  */ const hasStandardBrowserWebWorkerEnv = (()=>'undefined' != typeof WorkerGlobalScope && // eslint-disable-next-line no-undef
1051
1073
  self instanceof WorkerGlobalScope && 'function' == typeof self.importScripts)();
1052
1074
  const origin = hasBrowserEnv && window.location.href || 'http://localhost';
1053
- /* ESM default export */ const platform = {
1075
+ /* ESM default export */ const lib_platform = {
1054
1076
  ...common_utils_namespaceObject,
1055
1077
  ...browser
1056
1078
  };
1057
1079
  function toURLEncodedForm(data, options) {
1058
- return toFormData(data, new platform.classes.URLSearchParams(), Object.assign({
1080
+ return toFormData(data, new lib_platform.classes.URLSearchParams(), Object.assign({
1059
1081
  visitor: function(value, key, path, helpers) {
1060
- if (platform.isNode && utils.isBuffer(value)) {
1082
+ if (lib_platform.isNode && utils.isBuffer(value)) {
1061
1083
  this.append(key, value.toString('base64'));
1062
1084
  return false;
1063
1085
  }
@@ -1218,8 +1240,8 @@ const defaults_defaults = {
1218
1240
  maxContentLength: -1,
1219
1241
  maxBodyLength: -1,
1220
1242
  env: {
1221
- FormData: platform.classes.FormData,
1222
- Blob: platform.classes.Blob
1243
+ FormData: lib_platform.classes.FormData,
1244
+ Blob: lib_platform.classes.Blob
1223
1245
  },
1224
1246
  validateStatus: function(status) {
1225
1247
  return status >= 200 && status < 300;
@@ -1653,10 +1675,10 @@ const progressEventDecorator = (total, throttled)=>{
1653
1675
  ];
1654
1676
  };
1655
1677
  const asyncDecorator = (fn)=>(...args)=>utils.asap(()=>fn(...args));
1656
- /* ESM default export */ const helpers_isURLSameOrigin = platform.hasStandardBrowserEnv ? // Standard browser envs have full support of the APIs needed to test
1678
+ /* ESM default export */ const helpers_isURLSameOrigin = lib_platform.hasStandardBrowserEnv ? // Standard browser envs have full support of the APIs needed to test
1657
1679
  // whether the request URL is of the same origin as current location.
1658
1680
  function() {
1659
- const msie = platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent);
1681
+ const msie = lib_platform.navigator && /(msie|trident)/i.test(lib_platform.navigator.userAgent);
1660
1682
  const urlParsingNode = document.createElement('a');
1661
1683
  let originURL;
1662
1684
  /**
@@ -1700,7 +1722,7 @@ function() {
1700
1722
  return true;
1701
1723
  };
1702
1724
  }();
1703
- /* ESM default export */ const cookies = platform.hasStandardBrowserEnv ? // Standard browser envs support document.cookie
1725
+ /* ESM default export */ const cookies = lib_platform.hasStandardBrowserEnv ? // Standard browser envs support document.cookie
1704
1726
  {
1705
1727
  write (name, value, expires, path, domain, secure) {
1706
1728
  const cookie = [
@@ -1851,7 +1873,7 @@ const headersToObject = (thing)=>thing instanceof AxiosHeaders ? {
1851
1873
  if (auth) headers.set('Authorization', 'Basic ' + btoa((auth.username || '') + ':' + (auth.password ? unescape(encodeURIComponent(auth.password)) : '')));
1852
1874
  let contentType;
1853
1875
  if (utils.isFormData(data)) {
1854
- if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) headers.setContentType(void 0); // Let the browser set it
1876
+ if (lib_platform.hasStandardBrowserEnv || lib_platform.hasStandardBrowserWebWorkerEnv) headers.setContentType(void 0); // Let the browser set it
1855
1877
  else if (false !== (contentType = headers.getContentType())) {
1856
1878
  // fix semicolon duplication issue for ReactNative FormData implementation
1857
1879
  const [type, ...tokens] = contentType ? contentType.split(';').map((token)=>token.trim()).filter(Boolean) : [];
@@ -1864,7 +1886,7 @@ const headersToObject = (thing)=>thing instanceof AxiosHeaders ? {
1864
1886
  // Add xsrf header
1865
1887
  // This is only done if running in a standard browser environment.
1866
1888
  // Specifically not if we're in a web worker, or react-native.
1867
- if (platform.hasStandardBrowserEnv) {
1889
+ if (lib_platform.hasStandardBrowserEnv) {
1868
1890
  withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig));
1869
1891
  if (withXSRFToken || false !== withXSRFToken && helpers_isURLSameOrigin(newConfig.url)) {
1870
1892
  // Add xsrf header
@@ -1989,7 +2011,7 @@ const isXHRAdapterSupported = 'undefined' != typeof XMLHttpRequest;
1989
2011
  if (_config.signal) _config.signal.aborted ? onCanceled() : _config.signal.addEventListener('abort', onCanceled);
1990
2012
  }
1991
2013
  const protocol = parseProtocol(_config.url);
1992
- if (protocol && -1 === platform.protocols.indexOf(protocol)) {
2014
+ if (protocol && -1 === lib_platform.protocols.indexOf(protocol)) {
1993
2015
  reject(new core_AxiosError('Unsupported protocol ' + protocol + ':', core_AxiosError.ERR_BAD_REQUEST, config));
1994
2016
  return;
1995
2017
  }
@@ -2115,7 +2137,7 @@ const test = (fn, ...args)=>{
2115
2137
  };
2116
2138
  const supportsRequestStream = isReadableStreamSupported && test(()=>{
2117
2139
  let duplexAccessed = false;
2118
- const hasContentType = new Request(platform.origin, {
2140
+ const hasContentType = new Request(lib_platform.origin, {
2119
2141
  body: new ReadableStream(),
2120
2142
  method: 'POST',
2121
2143
  get duplex () {
@@ -2147,7 +2169,7 @@ const getBodyLength = async (body)=>{
2147
2169
  if (null == body) return 0;
2148
2170
  if (utils.isBlob(body)) return body.size;
2149
2171
  if (utils.isSpecCompliantForm(body)) {
2150
- const _request = new Request(platform.origin, {
2172
+ const _request = new Request(lib_platform.origin, {
2151
2173
  method: 'POST',
2152
2174
  body
2153
2175
  });
@@ -2822,26 +2844,12 @@ axios.default = axios;
2822
2844
  // Keep top-level export same with static properties
2823
2845
  // so that it can keep same with es module or cjs
2824
2846
  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;
2825
- var __webpack_modules__ = {
2826
- "?6728": function() {
2827
- /* (ignored) */ }
2828
- };
2829
- /************************************************************************/ // The module cache
2830
- var __webpack_module_cache__ = {};
2831
- // The require function
2832
- function __nested_webpack_require_293__(moduleId) {
2833
- // Check if module is in cache
2834
- var cachedModule = __webpack_module_cache__[moduleId];
2835
- if (void 0 !== cachedModule) return cachedModule.exports;
2836
- // Create a new module (and put it into the cache)
2837
- var module = __webpack_module_cache__[moduleId] = {
2838
- exports: {}
2839
- };
2840
- // Execute the module function
2841
- __webpack_modules__[moduleId](module, module.exports, __nested_webpack_require_293__);
2842
- // Return the exports of the module
2843
- return module.exports;
2844
- } /************************************************************************/
2847
+ // EXTERNAL MODULE: os (ignored)
2848
+ var os_ignored_ = __webpack_require__("?d2d5");
2849
+ // EXTERNAL MODULE: crypto (ignored)
2850
+ __webpack_require__("?d7f0");
2851
+ // EXTERNAL MODULE: jsonwebtoken (ignored)
2852
+ __webpack_require__("?fcd3");
2845
2853
  class APIResource {
2846
2854
  constructor(client){
2847
2855
  this._client = client;
@@ -3604,6 +3612,56 @@ class esm_Audio extends APIResource {
3604
3612
  super(...args), this.rooms = new Rooms(this._client), this.voices = new Voices(this._client), this.speech = new Speech(this._client);
3605
3613
  }
3606
3614
  }
3615
+ var package_namespaceObject = JSON.parse('{"name":"@coze/api","version":"1.0.10","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
3616
+ const { version: esm_version } = package_namespaceObject;
3617
+ const getEnv = ()=>{
3618
+ const nodeVersion = process.version.slice(1); // Remove 'v' prefix
3619
+ const { platform } = process;
3620
+ let osName = platform.toLowerCase();
3621
+ let osVersion = os_ignored_.release();
3622
+ if ('darwin' === platform) {
3623
+ osName = 'macos';
3624
+ // Try to parse the macOS version
3625
+ try {
3626
+ const darwinVersion = os_ignored_.release().split('.');
3627
+ if (darwinVersion.length >= 2) {
3628
+ const majorVersion = parseInt(darwinVersion[0], 10);
3629
+ if (!isNaN(majorVersion) && majorVersion >= 9) {
3630
+ const macVersion = majorVersion - 9;
3631
+ osVersion = `10.${macVersion}.${darwinVersion[1]}`;
3632
+ }
3633
+ }
3634
+ } catch (error) {
3635
+ // Keep the default os.release() value if parsing fails
3636
+ }
3637
+ } else if ('win32' === platform) {
3638
+ osName = 'windows';
3639
+ osVersion = os_ignored_.release();
3640
+ } else if ('linux' === platform) {
3641
+ osName = 'linux';
3642
+ osVersion = os_ignored_.release();
3643
+ }
3644
+ return {
3645
+ osName,
3646
+ osVersion,
3647
+ nodeVersion
3648
+ };
3649
+ };
3650
+ const getUserAgent = ()=>{
3651
+ const { nodeVersion, osName, osVersion } = getEnv();
3652
+ return `coze-js/${esm_version} node/${nodeVersion} ${osName}/${osVersion}`.toLowerCase();
3653
+ };
3654
+ const getNodeClientUserAgent = ()=>{
3655
+ const { osVersion, nodeVersion, osName } = getEnv();
3656
+ const ua = {
3657
+ version: esm_version,
3658
+ lang: 'node',
3659
+ lang_version: nodeVersion,
3660
+ os_name: osName,
3661
+ os_version: osVersion
3662
+ };
3663
+ return JSON.stringify(ua);
3664
+ };
3607
3665
  /* eslint-disable @typescript-eslint/no-explicit-any */ const esm_handleError = (error)=>{
3608
3666
  if (!error.isAxiosError && (!error.code || !error.message)) return new CozeError(`Unexpected error: ${error.message}`);
3609
3667
  if ('ECONNABORTED' === error.code && error.message.includes('timeout') || 'ETIMEDOUT' === error.code) {
@@ -3676,10 +3734,10 @@ async function fetchAPI(url) {
3676
3734
  const headers = {
3677
3735
  authorization: `Bearer ${this.token}`
3678
3736
  };
3679
- // FIXME: browser 下存在跨域问题,后续再看看
3680
- // if (!isBrowser()) {
3681
- // headers['agw-js-conv'] = 'str';
3682
- // }
3737
+ if (!isBrowser()) {
3738
+ headers['User-Agent'] = getUserAgent();
3739
+ headers['X-Coze-Client-User-Agent'] = getNodeClientUserAgent();
3740
+ }
3683
3741
  const config = esm_mergeConfig(this.axiosOptions, options, {
3684
3742
  headers
3685
3743
  });
@@ -3760,8 +3818,6 @@ APIClient.InternalServerError = InternalServerError;
3760
3818
  APIClient.GatewayError = GatewayError;
3761
3819
  APIClient.TimeoutError = TimeoutError;
3762
3820
  APIClient.UserAbortError = APIUserAbortError;
3763
- // EXTERNAL MODULE: crypto (ignored)
3764
- __nested_webpack_require_293__("?6728");
3765
3821
  class CozeAPI extends APIClient {
3766
3822
  constructor(...args){
3767
3823
  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);
@@ -38155,10 +38211,19 @@ var VERTC = _createClass(function e() {
38155
38211
  };
38156
38212
  /**
38157
38213
  * Check microphone permission,return boolean
38158
- */ const checkPermission = async ()=>(await index_esm_min_index.enableDevices({
38159
- audio: true,
38160
- video: false
38161
- })).audio;
38214
+ */ const checkPermission = async function() {
38215
+ let { audio = true, video = false } = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
38216
+ try {
38217
+ const result = await index_esm_min_index.enableDevices({
38218
+ audio,
38219
+ video
38220
+ });
38221
+ return result.audio;
38222
+ } catch (error) {
38223
+ console.error('Failed to check device permissions:', error);
38224
+ return false;
38225
+ }
38226
+ };
38162
38227
  /**
38163
38228
  * Get audio devices
38164
38229
  * @returns Promise<AudioDevices> Object containing arrays of audio input and output devices
@@ -38166,11 +38231,15 @@ var VERTC = _createClass(function e() {
38166
38231
  const devices = await index_esm_min_index.enumerateDevices();
38167
38232
  if (!(null == devices ? void 0 : devices.length)) return {
38168
38233
  audioInputs: [],
38169
- audioOutputs: []
38234
+ audioOutputs: [],
38235
+ videoInputs: [],
38236
+ videoOutputs: []
38170
38237
  };
38171
38238
  return {
38172
38239
  audioInputs: devices.filter((i)=>i.deviceId && 'audioinput' === i.kind),
38173
- audioOutputs: devices.filter((i)=>i.deviceId && 'audiooutput' === i.kind)
38240
+ audioOutputs: devices.filter((i)=>i.deviceId && 'audiooutput' === i.kind),
38241
+ videoInputs: devices.filter((i)=>i.deviceId && 'videoinput' === i.kind),
38242
+ videoOutputs: devices.filter((i)=>i.deviceId && 'videooutput' === i.kind)
38174
38243
  };
38175
38244
  };
38176
38245
  var error_RealtimeError = /*#__PURE__*/ function(RealtimeError) {
@@ -38184,12 +38253,20 @@ var error_RealtimeError = /*#__PURE__*/ function(RealtimeError) {
38184
38253
  RealtimeError["NETWORK_ERROR"] = "NETWORK_ERROR";
38185
38254
  RealtimeError["INVALID_STATE"] = "INVALID_STATE";
38186
38255
  RealtimeError["CREATE_ROOM_ERROR"] = "CREATE_ROOM_ERROR";
38256
+ RealtimeError["PARSE_MESSAGE_ERROR"] = "PARSE_MESSAGE_ERROR";
38257
+ RealtimeError["HANDLER_MESSAGE_ERROR"] = "HANDLER_MESSAGE_ERROR";
38187
38258
  return RealtimeError;
38188
38259
  }({});
38189
38260
  class RealtimeAPIError extends Error {
38190
- constructor(code, message){
38191
- super(`[${code}] ${message}`), this.code = code;
38261
+ /**
38262
+ * @param code - Error code
38263
+ * @param message - Error message
38264
+ * @param error - Error object
38265
+ */ constructor(code, message, error){
38266
+ super(`[${code}] ${message}`);
38192
38267
  this.name = 'RealtimeAPIError';
38268
+ this.code = code;
38269
+ this.error = error;
38193
38270
  }
38194
38271
  }
38195
38272
  var event_handler_EventNames = /*#__PURE__*/ function(EventNames) {
@@ -38226,6 +38303,18 @@ var event_handler_EventNames = /*#__PURE__*/ function(EventNames) {
38226
38303
  * zh: 客户端音频静音
38227
38304
  */ EventNames["AUDIO_MUTED"] = "client.audio.muted";
38228
38305
  /**
38306
+ * en: Client video on
38307
+ * zh: 客户端视频开启
38308
+ */ EventNames["VIDEO_ON"] = "client.video.on";
38309
+ /**
38310
+ * en: Client video off
38311
+ * zh: 客户端视频关闭
38312
+ */ EventNames["VIDEO_OFF"] = "client.video.off";
38313
+ /**
38314
+ * en: Client video event
38315
+ * zh: 客户端视频事件
38316
+ */ EventNames["PLAYER_EVENT"] = "client.video.event";
38317
+ /**
38229
38318
  * en: Client error
38230
38319
  * zh: 客户端错误
38231
38320
  */ EventNames["ERROR"] = "client.error";
@@ -38245,6 +38334,14 @@ var event_handler_EventNames = /*#__PURE__*/ function(EventNames) {
38245
38334
  * en: Audio output device changed
38246
38335
  * zh: 音频输出设备改变
38247
38336
  */ EventNames["AUDIO_OUTPUT_DEVICE_CHANGED"] = "client.output.device.changed";
38337
+ /**
38338
+ * en: Bot joined
38339
+ * zh: Bot 加入
38340
+ */ EventNames["BOT_JOIN"] = "server.bot.join";
38341
+ /**
38342
+ * en: Bot left
38343
+ * zh: Bot 离开
38344
+ */ EventNames["BOT_LEAVE"] = "server.bot.leave";
38248
38345
  return EventNames;
38249
38346
  }({});
38250
38347
  class RealtimeEventHandler {
@@ -38268,7 +38365,11 @@ class RealtimeEventHandler {
38268
38365
  }
38269
38366
  // eslint-disable-next-line max-params
38270
38367
  _dispatchToHandlers(eventName, event, handlers, prefix) {
38271
- for (const handler of handlers)if (!prefix || eventName.startsWith(prefix)) handler(eventName, event);
38368
+ for (const handler of handlers)if (!prefix || eventName.startsWith(prefix)) try {
38369
+ handler(eventName, event);
38370
+ } catch (e) {
38371
+ throw new RealtimeAPIError(error_RealtimeError.HANDLER_MESSAGE_ERROR, `Failed to handle message: ${eventName}`);
38372
+ }
38272
38373
  }
38273
38374
  dispatch(eventName, event) {
38274
38375
  this._log(`dispatch ${eventName} event`);
@@ -41540,6 +41641,7 @@ class EngineClient extends RealtimeEventHandler {
41540
41641
  this.engine.on(index_esm_min_index.events.onUserJoined, this.handleUserJoin);
41541
41642
  this.engine.on(index_esm_min_index.events.onUserLeave, this.handleUserLeave);
41542
41643
  this.engine.on(index_esm_min_index.events.onError, this.handleEventError);
41644
+ this.engine.on(index_esm_min_index.events.onPlayerEvent, this.handlePlayerEvent);
41543
41645
  if (this._debug) {
41544
41646
  this.engine.on(index_esm_min_index.events.onLocalAudioPropertiesReport, this.handleLocalAudioPropertiesReport);
41545
41647
  this.engine.on(index_esm_min_index.events.onRemoteAudioPropertiesReport, this.handleRemoteAudioPropertiesReport);
@@ -41550,45 +41652,62 @@ class EngineClient extends RealtimeEventHandler {
41550
41652
  this.engine.off(index_esm_min_index.events.onUserJoined, this.handleUserJoin);
41551
41653
  this.engine.off(index_esm_min_index.events.onUserLeave, this.handleUserLeave);
41552
41654
  this.engine.off(index_esm_min_index.events.onError, this.handleEventError);
41655
+ this.engine.off(index_esm_min_index.events.onPlayerEvent, this.handlePlayerEvent);
41553
41656
  if (this._debug) {
41554
41657
  this.engine.off(index_esm_min_index.events.onLocalAudioPropertiesReport, this.handleLocalAudioPropertiesReport);
41555
41658
  this.engine.off(index_esm_min_index.events.onRemoteAudioPropertiesReport, this.handleRemoteAudioPropertiesReport);
41556
41659
  }
41557
41660
  }
41661
+ _parseMessage(event) {
41662
+ try {
41663
+ return JSON.parse(event.message);
41664
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41665
+ } catch (e) {
41666
+ throw new RealtimeAPIError(error_RealtimeError.PARSE_MESSAGE_ERROR, (null == e ? void 0 : e.message) || 'Unknown error');
41667
+ }
41668
+ }
41558
41669
  handleMessage(event) {
41559
41670
  try {
41560
- const message = JSON.parse(event.message);
41671
+ const message = this._parseMessage(event);
41561
41672
  this.dispatch(`server.${message.event_type}`, message);
41562
41673
  } catch (e) {
41563
- this.dispatch('client.error', {
41564
- message: `Failed to parse message: ${event.message}`,
41565
- error: e
41566
- });
41674
+ if (e instanceof RealtimeAPIError) {
41675
+ if (e.code === error_RealtimeError.PARSE_MESSAGE_ERROR) this.dispatch(event_handler_EventNames.ERROR, {
41676
+ message: `Failed to parse message: ${event.message}`,
41677
+ error: e
41678
+ });
41679
+ else if (e.code === error_RealtimeError.HANDLER_MESSAGE_ERROR) this.dispatch(event_handler_EventNames.ERROR, {
41680
+ message: `Failed to handle message: ${event.message}`,
41681
+ error: e
41682
+ });
41683
+ } else this.dispatch(event_handler_EventNames.ERROR, e);
41567
41684
  }
41568
41685
  }
41569
41686
  handleEventError(e) {
41570
- this.dispatch('client.error', e);
41687
+ this.dispatch(event_handler_EventNames.ERROR, e);
41571
41688
  }
41572
41689
  handleUserJoin(event) {
41573
41690
  this.joinUserId = event.userInfo.userId;
41574
- this.dispatch('server.bot.join', event);
41691
+ this.dispatch(event_handler_EventNames.BOT_JOIN, event);
41575
41692
  }
41576
41693
  handleUserLeave(event) {
41577
- this.dispatch('server.bot.leave', event);
41694
+ this.dispatch(event_handler_EventNames.BOT_LEAVE, event);
41695
+ }
41696
+ handlePlayerEvent(event) {
41697
+ this.dispatch(event_handler_EventNames.PLAYER_EVENT, event);
41578
41698
  }
41579
41699
  async joinRoom(options) {
41580
- const { token, roomId, uid, audioMutedDefault = false } = options;
41700
+ const { token, roomId, uid, audioMutedDefault, videoOnDefault } = options;
41581
41701
  try {
41582
41702
  await this.engine.joinRoom(token, roomId, {
41583
41703
  userId: uid
41584
41704
  }, {
41585
41705
  isAutoPublish: !audioMutedDefault,
41586
41706
  isAutoSubscribeAudio: true,
41587
- isAutoSubscribeVideo: false
41707
+ isAutoSubscribeVideo: this._isSupportVideo && videoOnDefault
41588
41708
  });
41589
41709
  } catch (e) {
41590
41710
  if (e instanceof Error) throw new RealtimeAPIError(error_RealtimeError.CONNECTION_ERROR, e.message);
41591
- throw new RealtimeAPIError(error_RealtimeError.CONNECTION_ERROR, 'Unknown error');
41592
41711
  }
41593
41712
  }
41594
41713
  async setAudioInputDevice(deviceId) {
@@ -41602,19 +41721,26 @@ class EngineClient extends RealtimeEventHandler {
41602
41721
  if (-1 === devices.audioOutputs.findIndex((i)=>i.deviceId === deviceId)) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, `Audio output device not found: ${deviceId}`);
41603
41722
  await this.engine.setAudioPlaybackDevice(deviceId);
41604
41723
  }
41605
- async createLocalStream() {
41724
+ async createLocalStream(userId, videoConfig) {
41606
41725
  const devices = await getAudioDevices();
41607
41726
  if (!devices.audioInputs.length) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, 'Failed to get devices');
41727
+ if (this._isSupportVideo && !devices.videoInputs.length) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, 'Failed to get devices');
41608
41728
  await this.engine.startAudioCapture(devices.audioInputs[0].deviceId);
41729
+ if (this._isSupportVideo && (null == videoConfig ? void 0 : videoConfig.videoOnDefault)) await this.engine.startVideoCapture(devices.videoInputs[0].deviceId);
41730
+ if (this._isSupportVideo) this.engine.setLocalVideoPlayer(StreamIndex$1.STREAM_INDEX_MAIN, {
41731
+ renderDom: (null == videoConfig ? void 0 : videoConfig.renderDom) || 'local-player',
41732
+ userId
41733
+ });
41609
41734
  }
41610
41735
  async disconnect() {
41611
41736
  try {
41737
+ if (this._isSupportVideo) await this.engine.stopVideoCapture();
41612
41738
  await this.engine.stopAudioCapture();
41613
41739
  await this.engine.unpublishStream(MediaType$1.AUDIO);
41614
41740
  await this.engine.leaveRoom();
41615
41741
  this.removeEventListener();
41616
41742
  } catch (e) {
41617
- this.dispatch('client.error', e);
41743
+ this.dispatch(event_handler_EventNames.ERROR, e);
41618
41744
  throw e;
41619
41745
  }
41620
41746
  }
@@ -41623,7 +41749,16 @@ class EngineClient extends RealtimeEventHandler {
41623
41749
  if (isMicOn) await this.engine.publishStream(MediaType$1.AUDIO);
41624
41750
  else await this.engine.unpublishStream(MediaType$1.AUDIO);
41625
41751
  } catch (e) {
41626
- this.dispatch('client.error', e);
41752
+ this.dispatch(event_handler_EventNames.ERROR, e);
41753
+ throw e;
41754
+ }
41755
+ }
41756
+ async changeVideoState(isVideoOn) {
41757
+ try {
41758
+ if (isVideoOn) await this.engine.startVideoCapture();
41759
+ else await this.engine.stopVideoCapture();
41760
+ } catch (e) {
41761
+ this.dispatch(event_handler_EventNames.ERROR, e);
41627
41762
  throw e;
41628
41763
  }
41629
41764
  }
@@ -41636,7 +41771,7 @@ class EngineClient extends RealtimeEventHandler {
41636
41771
  }));
41637
41772
  this._log(`interrupt ${this.joinUserId} ${result}`);
41638
41773
  } catch (e) {
41639
- this.dispatch('client.error', e);
41774
+ this.dispatch(event_handler_EventNames.ERROR, e);
41640
41775
  throw e;
41641
41776
  }
41642
41777
  }
@@ -41645,7 +41780,7 @@ class EngineClient extends RealtimeEventHandler {
41645
41780
  const result = await this.engine.sendUserMessage(this.joinUserId, JSON.stringify(message));
41646
41781
  this._log(`sendMessage ${this.joinUserId} ${JSON.stringify(message)} ${result}`);
41647
41782
  } catch (e) {
41648
- this.dispatch('client.error', e);
41783
+ this.dispatch(event_handler_EventNames.ERROR, e);
41649
41784
  throw e;
41650
41785
  }
41651
41786
  }
@@ -41686,7 +41821,7 @@ class EngineClient extends RealtimeEventHandler {
41686
41821
  try {
41687
41822
  await this.engine.startAudioPlaybackDeviceTest('audio-test.wav', 200);
41688
41823
  } catch (e) {
41689
- this.dispatch('client.error', e);
41824
+ this.dispatch(event_handler_EventNames.ERROR, e);
41690
41825
  throw e;
41691
41826
  }
41692
41827
  }
@@ -41694,12 +41829,13 @@ class EngineClient extends RealtimeEventHandler {
41694
41829
  try {
41695
41830
  this.engine.stopAudioPlaybackDeviceTest();
41696
41831
  } catch (e) {
41697
- this.dispatch('client.error', e);
41832
+ this.dispatch(event_handler_EventNames.ERROR, e);
41698
41833
  throw e;
41699
41834
  }
41700
41835
  }
41701
- constructor(appId, debug = false, isTestEnv = false){
41702
- super(debug), this.joinUserId = '', this._AIAnsExtension = null;
41836
+ // eslint-disable-next-line max-params
41837
+ constructor(appId, debug = false, isTestEnv = false, isSupportVideo = false){
41838
+ super(debug), this.joinUserId = '', this._AIAnsExtension = null, this._isSupportVideo = false;
41703
41839
  if (isTestEnv) index_esm_min_index.setParameter('ICE_CONFIG_REQUEST_URLS', [
41704
41840
  'rtc-test.bytedance.com'
41705
41841
  ]);
@@ -41708,9 +41844,11 @@ class EngineClient extends RealtimeEventHandler {
41708
41844
  this.handleUserJoin = this.handleUserJoin.bind(this);
41709
41845
  this.handleUserLeave = this.handleUserLeave.bind(this);
41710
41846
  this.handleEventError = this.handleEventError.bind(this);
41847
+ this.handlePlayerEvent = this.handlePlayerEvent.bind(this);
41711
41848
  // Debug only
41712
41849
  this.handleLocalAudioPropertiesReport = this.handleLocalAudioPropertiesReport.bind(this);
41713
41850
  this.handleRemoteAudioPropertiesReport = this.handleRemoteAudioPropertiesReport.bind(this);
41851
+ this._isSupportVideo = isSupportVideo;
41714
41852
  }
41715
41853
  }
41716
41854
  class RealtimeClient extends RealtimeEventHandler {
@@ -41719,6 +41857,7 @@ class RealtimeClient extends RealtimeEventHandler {
41719
41857
  *
41720
41858
  * zh: 建立与 Coze API 的连接并加入房间
41721
41859
  */ async connect() {
41860
+ var _this__config_videoConfig;
41722
41861
  const { botId, conversationId, voiceId } = this._config;
41723
41862
  let roomInfo;
41724
41863
  try {
@@ -41731,11 +41870,10 @@ class RealtimeClient extends RealtimeEventHandler {
41731
41870
  });
41732
41871
  } catch (error) {
41733
41872
  this.dispatch(event_handler_EventNames.ERROR, error);
41734
- throw new RealtimeAPIError(error_RealtimeError.CREATE_ROOM_ERROR, error instanceof Error ? error.message : 'Unknown error');
41873
+ throw new RealtimeAPIError(error_RealtimeError.CREATE_ROOM_ERROR, error instanceof Error ? error.message : 'Unknown error', error);
41735
41874
  }
41736
- this._roomInfo = roomInfo;
41737
41875
  // Step2 create engine
41738
- this._client = new EngineClient(roomInfo.app_id, this._config.debug, this._isTestEnv);
41876
+ this._client = new EngineClient(roomInfo.app_id, this._config.debug, this._isTestEnv, this._isSupportVideo);
41739
41877
  // Step3 bind engine events
41740
41878
  this._client.bindEngineEvents();
41741
41879
  this._client.on(event_handler_EventNames.ALL, (eventName, data)=>{
@@ -41750,16 +41888,17 @@ class RealtimeClient extends RealtimeEventHandler {
41750
41888
  this._client.changeAIAnsExtension(true);
41751
41889
  this.dispatch(event_handler_EventNames.SUPPRESS_NON_STATIONARY_NOISE, {});
41752
41890
  }
41753
- var _this__config_audioMutedDefault;
41891
+ var _this__config_audioMutedDefault, _this__config_videoConfig_videoOnDefault;
41754
41892
  // Step4 join room
41755
41893
  await this._client.joinRoom({
41756
41894
  token: roomInfo.token,
41757
41895
  roomId: roomInfo.room_id,
41758
41896
  uid: roomInfo.uid,
41759
- audioMutedDefault: null !== (_this__config_audioMutedDefault = this._config.audioMutedDefault) && void 0 !== _this__config_audioMutedDefault && _this__config_audioMutedDefault
41897
+ audioMutedDefault: null !== (_this__config_audioMutedDefault = this._config.audioMutedDefault) && void 0 !== _this__config_audioMutedDefault && _this__config_audioMutedDefault,
41898
+ 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
41760
41899
  });
41761
41900
  // Step5 create local stream
41762
- await this._client.createLocalStream();
41901
+ await this._client.createLocalStream(roomInfo.uid, this._config.videoConfig);
41763
41902
  // step6 set connected and dispatch connected event
41764
41903
  this.isConnected = true;
41765
41904
  this.dispatch(event_handler_EventNames.CONNECTED, {
@@ -41810,6 +41949,12 @@ class RealtimeClient extends RealtimeEventHandler {
41810
41949
  if (isEnable) this.dispatch(event_handler_EventNames.AUDIO_UNMUTED, {});
41811
41950
  else this.dispatch(event_handler_EventNames.AUDIO_MUTED, {});
41812
41951
  }
41952
+ async setVideoEnable(isEnable) {
41953
+ var _this__client;
41954
+ await (null === (_this__client = this._client) || void 0 === _this__client ? void 0 : _this__client.changeVideoState(isEnable));
41955
+ if (isEnable) this.dispatch(event_handler_EventNames.VIDEO_ON, {});
41956
+ else this.dispatch(event_handler_EventNames.VIDEO_OFF, {});
41957
+ }
41813
41958
  /**
41814
41959
  * en: Enable audio properties reporting (debug mode only)
41815
41960
  *
@@ -41895,7 +42040,7 @@ class RealtimeClient extends RealtimeEventHandler {
41895
42040
  * @param config.suppressNonStationaryNoise - Optional, suppress non-stationary noise, defaults to false. |
41896
42041
  * 可选,默认是否抑制非静态噪声,默认值为 false。
41897
42042
  */ constructor(config){
41898
- super(config.debug), this._client = null, this._roomInfo = null, this.isConnected = false, this._isTestEnv = false;
42043
+ super(config.debug), this._client = null, this.isConnected = false, this._isTestEnv = false, this._isSupportVideo = false;
41899
42044
  this._config = config;
41900
42045
  var _this__config_baseURL;
41901
42046
  const defaultBaseURL = null !== (_this__config_baseURL = this._config.baseURL) && void 0 !== _this__config_baseURL ? _this__config_baseURL : 'https://api.coze.cn';
@@ -41907,6 +42052,7 @@ class RealtimeClient extends RealtimeEventHandler {
41907
42052
  allowPersonalAccessTokenInBrowser: this._config.allowPersonalAccessTokenInBrowser
41908
42053
  });
41909
42054
  this._isTestEnv = 'https://api.coze.cn' !== defaultBaseURL;
42055
+ this._isSupportVideo = !!config.videoConfig;
41910
42056
  }
41911
42057
  }
41912
42058
  export { event_handler_EventNames as EventNames, RealtimeAPIError, RealtimeClient, error_RealtimeError as RealtimeError, src_utils_namespaceObject as RealtimeUtils };
@@ -1,27 +1,33 @@
1
1
  import { type AudioPropertiesConfig, type onUserJoinedEvent, type onUserLeaveEvent, type UserMessageEvent } from '@volcengine/rtc';
2
2
  import { RealtimeEventHandler } from './event-handler';
3
+ import { type VideoConfig } from '.';
3
4
  export declare class EngineClient extends RealtimeEventHandler {
4
5
  private engine;
5
6
  private joinUserId;
6
7
  private _AIAnsExtension;
7
- constructor(appId: string, debug?: boolean, isTestEnv?: boolean);
8
+ private _isSupportVideo;
9
+ constructor(appId: string, debug?: boolean, isTestEnv?: boolean, isSupportVideo?: boolean);
8
10
  bindEngineEvents(): void;
9
11
  removeEventListener(): void;
12
+ _parseMessage(event: UserMessageEvent): any;
10
13
  handleMessage(event: UserMessageEvent): void;
11
14
  handleEventError(e: unknown): void;
12
15
  handleUserJoin(event: onUserJoinedEvent): void;
13
16
  handleUserLeave(event: onUserLeaveEvent): void;
17
+ handlePlayerEvent(event: unknown): void;
14
18
  joinRoom(options: {
15
19
  token: string;
16
20
  roomId: string;
17
21
  uid: string;
18
22
  audioMutedDefault?: boolean;
23
+ videoOnDefault?: boolean;
19
24
  }): Promise<void>;
20
25
  setAudioInputDevice(deviceId: string): Promise<void>;
21
26
  setAudioOutputDevice(deviceId: string): Promise<void>;
22
- createLocalStream(): Promise<void>;
27
+ createLocalStream(userId?: string, videoConfig?: VideoConfig): Promise<void>;
23
28
  disconnect(): Promise<void>;
24
29
  changeAudioState(isMicOn: boolean): Promise<void>;
30
+ changeVideoState(isVideoOn: boolean): Promise<void>;
25
31
  stop(): Promise<void>;
26
32
  sendMessage(message: Record<string, unknown>): Promise<void>;
27
33
  enableAudioPropertiesReport(config?: AudioPropertiesConfig): void;
@@ -8,10 +8,18 @@ export declare enum RealtimeError {
8
8
  PERMISSION_DENIED = "PERMISSION_DENIED",
9
9
  NETWORK_ERROR = "NETWORK_ERROR",
10
10
  INVALID_STATE = "INVALID_STATE",
11
- CREATE_ROOM_ERROR = "CREATE_ROOM_ERROR"
11
+ CREATE_ROOM_ERROR = "CREATE_ROOM_ERROR",
12
+ PARSE_MESSAGE_ERROR = "PARSE_MESSAGE_ERROR",
13
+ HANDLER_MESSAGE_ERROR = "HANDLER_MESSAGE_ERROR"
12
14
  }
13
15
  export declare const ErrorMessages: Record<RealtimeError, string>;
14
16
  export declare class RealtimeAPIError extends Error {
15
17
  code: RealtimeError;
16
- constructor(code: RealtimeError, message: string);
18
+ error?: unknown;
19
+ /**
20
+ * @param code - Error code
21
+ * @param message - Error message
22
+ * @param error - Error object
23
+ */
24
+ constructor(code: RealtimeError, message: string, error?: unknown);
17
25
  }