@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/umd/index.js CHANGED
@@ -6,8 +6,30 @@
6
6
  else root["CozeRealtimeApi"] = factory();
7
7
  })(self, ()=>(()=>{
8
8
  "use strict";
9
- // The require scope
10
- var __webpack_require__ = {};
9
+ var __webpack_modules__ = {
10
+ "?d7f0": function() {
11
+ /* (ignored) */ },
12
+ "?fcd3": function() {
13
+ /* (ignored) */ },
14
+ "?d2d5": function() {
15
+ /* (ignored) */ }
16
+ };
17
+ /************************************************************************/ // The module cache
18
+ var __webpack_module_cache__ = {};
19
+ // The require function
20
+ function __webpack_require__(moduleId) {
21
+ // Check if module is in cache
22
+ var cachedModule = __webpack_module_cache__[moduleId];
23
+ if (void 0 !== cachedModule) return cachedModule.exports;
24
+ // Create a new module (and put it into the cache)
25
+ var module1 = __webpack_module_cache__[moduleId] = {
26
+ exports: {}
27
+ };
28
+ // Execute the module function
29
+ __webpack_modules__[moduleId](module1, module1.exports, __webpack_require__);
30
+ // Return the exports of the module
31
+ return module1.exports;
32
+ }
11
33
  /************************************************************************/ // webpack/runtime/define_property_getters
12
34
  (()=>{
13
35
  __webpack_require__.d = function(exports1, definition) {
@@ -1068,14 +1090,14 @@
1068
1090
  */ const hasStandardBrowserWebWorkerEnv = (()=>'undefined' != typeof WorkerGlobalScope && // eslint-disable-next-line no-undef
1069
1091
  self instanceof WorkerGlobalScope && 'function' == typeof self.importScripts)();
1070
1092
  const origin = hasBrowserEnv && window.location.href || 'http://localhost';
1071
- /* ESM default export */ const platform = {
1093
+ /* ESM default export */ const lib_platform = {
1072
1094
  ...common_utils_namespaceObject,
1073
1095
  ...browser
1074
1096
  };
1075
1097
  function toURLEncodedForm(data, options) {
1076
- return toFormData(data, new platform.classes.URLSearchParams(), Object.assign({
1098
+ return toFormData(data, new lib_platform.classes.URLSearchParams(), Object.assign({
1077
1099
  visitor: function(value, key, path, helpers) {
1078
- if (platform.isNode && utils.isBuffer(value)) {
1100
+ if (lib_platform.isNode && utils.isBuffer(value)) {
1079
1101
  this.append(key, value.toString('base64'));
1080
1102
  return false;
1081
1103
  }
@@ -1236,8 +1258,8 @@
1236
1258
  maxContentLength: -1,
1237
1259
  maxBodyLength: -1,
1238
1260
  env: {
1239
- FormData: platform.classes.FormData,
1240
- Blob: platform.classes.Blob
1261
+ FormData: lib_platform.classes.FormData,
1262
+ Blob: lib_platform.classes.Blob
1241
1263
  },
1242
1264
  validateStatus: function(status) {
1243
1265
  return status >= 200 && status < 300;
@@ -1671,10 +1693,10 @@
1671
1693
  ];
1672
1694
  };
1673
1695
  const asyncDecorator = (fn)=>(...args)=>utils.asap(()=>fn(...args));
1674
- /* ESM default export */ const helpers_isURLSameOrigin = platform.hasStandardBrowserEnv ? // Standard browser envs have full support of the APIs needed to test
1696
+ /* ESM default export */ const helpers_isURLSameOrigin = lib_platform.hasStandardBrowserEnv ? // Standard browser envs have full support of the APIs needed to test
1675
1697
  // whether the request URL is of the same origin as current location.
1676
1698
  function() {
1677
- const msie = platform.navigator && /(msie|trident)/i.test(platform.navigator.userAgent);
1699
+ const msie = lib_platform.navigator && /(msie|trident)/i.test(lib_platform.navigator.userAgent);
1678
1700
  const urlParsingNode = document.createElement('a');
1679
1701
  let originURL;
1680
1702
  /**
@@ -1718,7 +1740,7 @@
1718
1740
  return true;
1719
1741
  };
1720
1742
  }();
1721
- /* ESM default export */ const cookies = platform.hasStandardBrowserEnv ? // Standard browser envs support document.cookie
1743
+ /* ESM default export */ const cookies = lib_platform.hasStandardBrowserEnv ? // Standard browser envs support document.cookie
1722
1744
  {
1723
1745
  write (name, value, expires, path, domain, secure) {
1724
1746
  const cookie = [
@@ -1869,7 +1891,7 @@
1869
1891
  if (auth) headers.set('Authorization', 'Basic ' + btoa((auth.username || '') + ':' + (auth.password ? unescape(encodeURIComponent(auth.password)) : '')));
1870
1892
  let contentType;
1871
1893
  if (utils.isFormData(data)) {
1872
- if (platform.hasStandardBrowserEnv || platform.hasStandardBrowserWebWorkerEnv) headers.setContentType(void 0); // Let the browser set it
1894
+ if (lib_platform.hasStandardBrowserEnv || lib_platform.hasStandardBrowserWebWorkerEnv) headers.setContentType(void 0); // Let the browser set it
1873
1895
  else if (false !== (contentType = headers.getContentType())) {
1874
1896
  // fix semicolon duplication issue for ReactNative FormData implementation
1875
1897
  const [type, ...tokens] = contentType ? contentType.split(';').map((token)=>token.trim()).filter(Boolean) : [];
@@ -1882,7 +1904,7 @@
1882
1904
  // Add xsrf header
1883
1905
  // This is only done if running in a standard browser environment.
1884
1906
  // Specifically not if we're in a web worker, or react-native.
1885
- if (platform.hasStandardBrowserEnv) {
1907
+ if (lib_platform.hasStandardBrowserEnv) {
1886
1908
  withXSRFToken && utils.isFunction(withXSRFToken) && (withXSRFToken = withXSRFToken(newConfig));
1887
1909
  if (withXSRFToken || false !== withXSRFToken && helpers_isURLSameOrigin(newConfig.url)) {
1888
1910
  // Add xsrf header
@@ -2007,7 +2029,7 @@
2007
2029
  if (_config.signal) _config.signal.aborted ? onCanceled() : _config.signal.addEventListener('abort', onCanceled);
2008
2030
  }
2009
2031
  const protocol = parseProtocol(_config.url);
2010
- if (protocol && -1 === platform.protocols.indexOf(protocol)) {
2032
+ if (protocol && -1 === lib_platform.protocols.indexOf(protocol)) {
2011
2033
  reject(new core_AxiosError('Unsupported protocol ' + protocol + ':', core_AxiosError.ERR_BAD_REQUEST, config));
2012
2034
  return;
2013
2035
  }
@@ -2133,7 +2155,7 @@
2133
2155
  };
2134
2156
  const supportsRequestStream = isReadableStreamSupported && test(()=>{
2135
2157
  let duplexAccessed = false;
2136
- const hasContentType = new Request(platform.origin, {
2158
+ const hasContentType = new Request(lib_platform.origin, {
2137
2159
  body: new ReadableStream(),
2138
2160
  method: 'POST',
2139
2161
  get duplex () {
@@ -2165,7 +2187,7 @@
2165
2187
  if (null == body) return 0;
2166
2188
  if (utils.isBlob(body)) return body.size;
2167
2189
  if (utils.isSpecCompliantForm(body)) {
2168
- const _request = new Request(platform.origin, {
2190
+ const _request = new Request(lib_platform.origin, {
2169
2191
  method: 'POST',
2170
2192
  body
2171
2193
  });
@@ -2840,26 +2862,12 @@
2840
2862
  // Keep top-level export same with static properties
2841
2863
  // so that it can keep same with es module or cjs
2842
2864
  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;
2843
- var __webpack_modules__ = {
2844
- "?6728": function() {
2845
- /* (ignored) */ }
2846
- };
2847
- /************************************************************************/ // The module cache
2848
- var __webpack_module_cache__ = {};
2849
- // The require function
2850
- function __nested_webpack_require_293__(moduleId) {
2851
- // Check if module is in cache
2852
- var cachedModule = __webpack_module_cache__[moduleId];
2853
- if (void 0 !== cachedModule) return cachedModule.exports;
2854
- // Create a new module (and put it into the cache)
2855
- var module1 = __webpack_module_cache__[moduleId] = {
2856
- exports: {}
2857
- };
2858
- // Execute the module function
2859
- __webpack_modules__[moduleId](module1, module1.exports, __nested_webpack_require_293__);
2860
- // Return the exports of the module
2861
- return module1.exports;
2862
- } /************************************************************************/
2865
+ // EXTERNAL MODULE: os (ignored)
2866
+ var os_ignored_ = __webpack_require__("?d2d5");
2867
+ // EXTERNAL MODULE: crypto (ignored)
2868
+ __webpack_require__("?d7f0");
2869
+ // EXTERNAL MODULE: jsonwebtoken (ignored)
2870
+ __webpack_require__("?fcd3");
2863
2871
  class APIResource {
2864
2872
  constructor(client){
2865
2873
  this._client = client;
@@ -3622,6 +3630,56 @@
3622
3630
  super(...args), this.rooms = new Rooms(this._client), this.voices = new Voices(this._client), this.speech = new Speech(this._client);
3623
3631
  }
3624
3632
  }
3633
+ 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
3634
+ const { version: esm_version } = package_namespaceObject;
3635
+ const getEnv = ()=>{
3636
+ const nodeVersion = process.version.slice(1); // Remove 'v' prefix
3637
+ const { platform } = process;
3638
+ let osName = platform.toLowerCase();
3639
+ let osVersion = os_ignored_.release();
3640
+ if ('darwin' === platform) {
3641
+ osName = 'macos';
3642
+ // Try to parse the macOS version
3643
+ try {
3644
+ const darwinVersion = os_ignored_.release().split('.');
3645
+ if (darwinVersion.length >= 2) {
3646
+ const majorVersion = parseInt(darwinVersion[0], 10);
3647
+ if (!isNaN(majorVersion) && majorVersion >= 9) {
3648
+ const macVersion = majorVersion - 9;
3649
+ osVersion = `10.${macVersion}.${darwinVersion[1]}`;
3650
+ }
3651
+ }
3652
+ } catch (error) {
3653
+ // Keep the default os.release() value if parsing fails
3654
+ }
3655
+ } else if ('win32' === platform) {
3656
+ osName = 'windows';
3657
+ osVersion = os_ignored_.release();
3658
+ } else if ('linux' === platform) {
3659
+ osName = 'linux';
3660
+ osVersion = os_ignored_.release();
3661
+ }
3662
+ return {
3663
+ osName,
3664
+ osVersion,
3665
+ nodeVersion
3666
+ };
3667
+ };
3668
+ const getUserAgent = ()=>{
3669
+ const { nodeVersion, osName, osVersion } = getEnv();
3670
+ return `coze-js/${esm_version} node/${nodeVersion} ${osName}/${osVersion}`.toLowerCase();
3671
+ };
3672
+ const getNodeClientUserAgent = ()=>{
3673
+ const { osVersion, nodeVersion, osName } = getEnv();
3674
+ const ua = {
3675
+ version: esm_version,
3676
+ lang: 'node',
3677
+ lang_version: nodeVersion,
3678
+ os_name: osName,
3679
+ os_version: osVersion
3680
+ };
3681
+ return JSON.stringify(ua);
3682
+ };
3625
3683
  /* eslint-disable @typescript-eslint/no-explicit-any */ const esm_handleError = (error)=>{
3626
3684
  if (!error.isAxiosError && (!error.code || !error.message)) return new CozeError(`Unexpected error: ${error.message}`);
3627
3685
  if ('ECONNABORTED' === error.code && error.message.includes('timeout') || 'ETIMEDOUT' === error.code) {
@@ -3694,10 +3752,10 @@
3694
3752
  const headers = {
3695
3753
  authorization: `Bearer ${this.token}`
3696
3754
  };
3697
- // FIXME: browser 下存在跨域问题,后续再看看
3698
- // if (!isBrowser()) {
3699
- // headers['agw-js-conv'] = 'str';
3700
- // }
3755
+ if (!isBrowser()) {
3756
+ headers['User-Agent'] = getUserAgent();
3757
+ headers['X-Coze-Client-User-Agent'] = getNodeClientUserAgent();
3758
+ }
3701
3759
  const config = esm_mergeConfig(this.axiosOptions, options, {
3702
3760
  headers
3703
3761
  });
@@ -3778,8 +3836,6 @@
3778
3836
  APIClient.GatewayError = GatewayError;
3779
3837
  APIClient.TimeoutError = TimeoutError;
3780
3838
  APIClient.UserAbortError = APIUserAbortError;
3781
- // EXTERNAL MODULE: crypto (ignored)
3782
- __nested_webpack_require_293__("?6728");
3783
3839
  class CozeAPI extends APIClient {
3784
3840
  constructor(...args){
3785
3841
  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);
@@ -38173,10 +38229,19 @@
38173
38229
  };
38174
38230
  /**
38175
38231
  * Check microphone permission,return boolean
38176
- */ const checkPermission = async ()=>(await index_esm_min_index.enableDevices({
38177
- audio: true,
38178
- video: false
38179
- })).audio;
38232
+ */ const checkPermission = async function() {
38233
+ let { audio = true, video = false } = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
38234
+ try {
38235
+ const result = await index_esm_min_index.enableDevices({
38236
+ audio,
38237
+ video
38238
+ });
38239
+ return result.audio;
38240
+ } catch (error) {
38241
+ console.error('Failed to check device permissions:', error);
38242
+ return false;
38243
+ }
38244
+ };
38180
38245
  /**
38181
38246
  * Get audio devices
38182
38247
  * @returns Promise<AudioDevices> Object containing arrays of audio input and output devices
@@ -38184,11 +38249,15 @@
38184
38249
  const devices = await index_esm_min_index.enumerateDevices();
38185
38250
  if (!(null == devices ? void 0 : devices.length)) return {
38186
38251
  audioInputs: [],
38187
- audioOutputs: []
38252
+ audioOutputs: [],
38253
+ videoInputs: [],
38254
+ videoOutputs: []
38188
38255
  };
38189
38256
  return {
38190
38257
  audioInputs: devices.filter((i)=>i.deviceId && 'audioinput' === i.kind),
38191
- audioOutputs: devices.filter((i)=>i.deviceId && 'audiooutput' === i.kind)
38258
+ audioOutputs: devices.filter((i)=>i.deviceId && 'audiooutput' === i.kind),
38259
+ videoInputs: devices.filter((i)=>i.deviceId && 'videoinput' === i.kind),
38260
+ videoOutputs: devices.filter((i)=>i.deviceId && 'videooutput' === i.kind)
38192
38261
  };
38193
38262
  };
38194
38263
  var error_RealtimeError = /*#__PURE__*/ function(RealtimeError) {
@@ -38202,12 +38271,20 @@
38202
38271
  RealtimeError["NETWORK_ERROR"] = "NETWORK_ERROR";
38203
38272
  RealtimeError["INVALID_STATE"] = "INVALID_STATE";
38204
38273
  RealtimeError["CREATE_ROOM_ERROR"] = "CREATE_ROOM_ERROR";
38274
+ RealtimeError["PARSE_MESSAGE_ERROR"] = "PARSE_MESSAGE_ERROR";
38275
+ RealtimeError["HANDLER_MESSAGE_ERROR"] = "HANDLER_MESSAGE_ERROR";
38205
38276
  return RealtimeError;
38206
38277
  }({});
38207
38278
  class RealtimeAPIError extends Error {
38208
- constructor(code, message){
38209
- super(`[${code}] ${message}`), this.code = code;
38279
+ /**
38280
+ * @param code - Error code
38281
+ * @param message - Error message
38282
+ * @param error - Error object
38283
+ */ constructor(code, message, error){
38284
+ super(`[${code}] ${message}`);
38210
38285
  this.name = 'RealtimeAPIError';
38286
+ this.code = code;
38287
+ this.error = error;
38211
38288
  }
38212
38289
  }
38213
38290
  var event_handler_EventNames = /*#__PURE__*/ function(EventNames) {
@@ -38244,6 +38321,18 @@
38244
38321
  * zh: 客户端音频静音
38245
38322
  */ EventNames["AUDIO_MUTED"] = "client.audio.muted";
38246
38323
  /**
38324
+ * en: Client video on
38325
+ * zh: 客户端视频开启
38326
+ */ EventNames["VIDEO_ON"] = "client.video.on";
38327
+ /**
38328
+ * en: Client video off
38329
+ * zh: 客户端视频关闭
38330
+ */ EventNames["VIDEO_OFF"] = "client.video.off";
38331
+ /**
38332
+ * en: Client video event
38333
+ * zh: 客户端视频事件
38334
+ */ EventNames["PLAYER_EVENT"] = "client.video.event";
38335
+ /**
38247
38336
  * en: Client error
38248
38337
  * zh: 客户端错误
38249
38338
  */ EventNames["ERROR"] = "client.error";
@@ -38263,6 +38352,14 @@
38263
38352
  * en: Audio output device changed
38264
38353
  * zh: 音频输出设备改变
38265
38354
  */ EventNames["AUDIO_OUTPUT_DEVICE_CHANGED"] = "client.output.device.changed";
38355
+ /**
38356
+ * en: Bot joined
38357
+ * zh: Bot 加入
38358
+ */ EventNames["BOT_JOIN"] = "server.bot.join";
38359
+ /**
38360
+ * en: Bot left
38361
+ * zh: Bot 离开
38362
+ */ EventNames["BOT_LEAVE"] = "server.bot.leave";
38266
38363
  return EventNames;
38267
38364
  }({});
38268
38365
  class RealtimeEventHandler {
@@ -38286,7 +38383,11 @@
38286
38383
  }
38287
38384
  // eslint-disable-next-line max-params
38288
38385
  _dispatchToHandlers(eventName, event, handlers, prefix) {
38289
- for (const handler of handlers)if (!prefix || eventName.startsWith(prefix)) handler(eventName, event);
38386
+ for (const handler of handlers)if (!prefix || eventName.startsWith(prefix)) try {
38387
+ handler(eventName, event);
38388
+ } catch (e) {
38389
+ throw new RealtimeAPIError(error_RealtimeError.HANDLER_MESSAGE_ERROR, `Failed to handle message: ${eventName}`);
38390
+ }
38290
38391
  }
38291
38392
  dispatch(eventName, event) {
38292
38393
  this._log(`dispatch ${eventName} event`);
@@ -41558,6 +41659,7 @@
41558
41659
  this.engine.on(index_esm_min_index.events.onUserJoined, this.handleUserJoin);
41559
41660
  this.engine.on(index_esm_min_index.events.onUserLeave, this.handleUserLeave);
41560
41661
  this.engine.on(index_esm_min_index.events.onError, this.handleEventError);
41662
+ this.engine.on(index_esm_min_index.events.onPlayerEvent, this.handlePlayerEvent);
41561
41663
  if (this._debug) {
41562
41664
  this.engine.on(index_esm_min_index.events.onLocalAudioPropertiesReport, this.handleLocalAudioPropertiesReport);
41563
41665
  this.engine.on(index_esm_min_index.events.onRemoteAudioPropertiesReport, this.handleRemoteAudioPropertiesReport);
@@ -41568,45 +41670,62 @@
41568
41670
  this.engine.off(index_esm_min_index.events.onUserJoined, this.handleUserJoin);
41569
41671
  this.engine.off(index_esm_min_index.events.onUserLeave, this.handleUserLeave);
41570
41672
  this.engine.off(index_esm_min_index.events.onError, this.handleEventError);
41673
+ this.engine.off(index_esm_min_index.events.onPlayerEvent, this.handlePlayerEvent);
41571
41674
  if (this._debug) {
41572
41675
  this.engine.off(index_esm_min_index.events.onLocalAudioPropertiesReport, this.handleLocalAudioPropertiesReport);
41573
41676
  this.engine.off(index_esm_min_index.events.onRemoteAudioPropertiesReport, this.handleRemoteAudioPropertiesReport);
41574
41677
  }
41575
41678
  }
41679
+ _parseMessage(event) {
41680
+ try {
41681
+ return JSON.parse(event.message);
41682
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
41683
+ } catch (e) {
41684
+ throw new RealtimeAPIError(error_RealtimeError.PARSE_MESSAGE_ERROR, (null == e ? void 0 : e.message) || 'Unknown error');
41685
+ }
41686
+ }
41576
41687
  handleMessage(event) {
41577
41688
  try {
41578
- const message = JSON.parse(event.message);
41689
+ const message = this._parseMessage(event);
41579
41690
  this.dispatch(`server.${message.event_type}`, message);
41580
41691
  } catch (e) {
41581
- this.dispatch('client.error', {
41582
- message: `Failed to parse message: ${event.message}`,
41583
- error: e
41584
- });
41692
+ if (e instanceof RealtimeAPIError) {
41693
+ if (e.code === error_RealtimeError.PARSE_MESSAGE_ERROR) this.dispatch(event_handler_EventNames.ERROR, {
41694
+ message: `Failed to parse message: ${event.message}`,
41695
+ error: e
41696
+ });
41697
+ else if (e.code === error_RealtimeError.HANDLER_MESSAGE_ERROR) this.dispatch(event_handler_EventNames.ERROR, {
41698
+ message: `Failed to handle message: ${event.message}`,
41699
+ error: e
41700
+ });
41701
+ } else this.dispatch(event_handler_EventNames.ERROR, e);
41585
41702
  }
41586
41703
  }
41587
41704
  handleEventError(e) {
41588
- this.dispatch('client.error', e);
41705
+ this.dispatch(event_handler_EventNames.ERROR, e);
41589
41706
  }
41590
41707
  handleUserJoin(event) {
41591
41708
  this.joinUserId = event.userInfo.userId;
41592
- this.dispatch('server.bot.join', event);
41709
+ this.dispatch(event_handler_EventNames.BOT_JOIN, event);
41593
41710
  }
41594
41711
  handleUserLeave(event) {
41595
- this.dispatch('server.bot.leave', event);
41712
+ this.dispatch(event_handler_EventNames.BOT_LEAVE, event);
41713
+ }
41714
+ handlePlayerEvent(event) {
41715
+ this.dispatch(event_handler_EventNames.PLAYER_EVENT, event);
41596
41716
  }
41597
41717
  async joinRoom(options) {
41598
- const { token, roomId, uid, audioMutedDefault = false } = options;
41718
+ const { token, roomId, uid, audioMutedDefault, videoOnDefault } = options;
41599
41719
  try {
41600
41720
  await this.engine.joinRoom(token, roomId, {
41601
41721
  userId: uid
41602
41722
  }, {
41603
41723
  isAutoPublish: !audioMutedDefault,
41604
41724
  isAutoSubscribeAudio: true,
41605
- isAutoSubscribeVideo: false
41725
+ isAutoSubscribeVideo: this._isSupportVideo && videoOnDefault
41606
41726
  });
41607
41727
  } catch (e) {
41608
41728
  if (e instanceof Error) throw new RealtimeAPIError(error_RealtimeError.CONNECTION_ERROR, e.message);
41609
- throw new RealtimeAPIError(error_RealtimeError.CONNECTION_ERROR, 'Unknown error');
41610
41729
  }
41611
41730
  }
41612
41731
  async setAudioInputDevice(deviceId) {
@@ -41620,19 +41739,26 @@
41620
41739
  if (-1 === devices.audioOutputs.findIndex((i)=>i.deviceId === deviceId)) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, `Audio output device not found: ${deviceId}`);
41621
41740
  await this.engine.setAudioPlaybackDevice(deviceId);
41622
41741
  }
41623
- async createLocalStream() {
41742
+ async createLocalStream(userId, videoConfig) {
41624
41743
  const devices = await getAudioDevices();
41625
41744
  if (!devices.audioInputs.length) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, 'Failed to get devices');
41745
+ if (this._isSupportVideo && !devices.videoInputs.length) throw new RealtimeAPIError(error_RealtimeError.DEVICE_ACCESS_ERROR, 'Failed to get devices');
41626
41746
  await this.engine.startAudioCapture(devices.audioInputs[0].deviceId);
41747
+ if (this._isSupportVideo && (null == videoConfig ? void 0 : videoConfig.videoOnDefault)) await this.engine.startVideoCapture(devices.videoInputs[0].deviceId);
41748
+ if (this._isSupportVideo) this.engine.setLocalVideoPlayer(StreamIndex$1.STREAM_INDEX_MAIN, {
41749
+ renderDom: (null == videoConfig ? void 0 : videoConfig.renderDom) || 'local-player',
41750
+ userId
41751
+ });
41627
41752
  }
41628
41753
  async disconnect() {
41629
41754
  try {
41755
+ if (this._isSupportVideo) await this.engine.stopVideoCapture();
41630
41756
  await this.engine.stopAudioCapture();
41631
41757
  await this.engine.unpublishStream(MediaType$1.AUDIO);
41632
41758
  await this.engine.leaveRoom();
41633
41759
  this.removeEventListener();
41634
41760
  } catch (e) {
41635
- this.dispatch('client.error', e);
41761
+ this.dispatch(event_handler_EventNames.ERROR, e);
41636
41762
  throw e;
41637
41763
  }
41638
41764
  }
@@ -41641,7 +41767,16 @@
41641
41767
  if (isMicOn) await this.engine.publishStream(MediaType$1.AUDIO);
41642
41768
  else await this.engine.unpublishStream(MediaType$1.AUDIO);
41643
41769
  } catch (e) {
41644
- this.dispatch('client.error', e);
41770
+ this.dispatch(event_handler_EventNames.ERROR, e);
41771
+ throw e;
41772
+ }
41773
+ }
41774
+ async changeVideoState(isVideoOn) {
41775
+ try {
41776
+ if (isVideoOn) await this.engine.startVideoCapture();
41777
+ else await this.engine.stopVideoCapture();
41778
+ } catch (e) {
41779
+ this.dispatch(event_handler_EventNames.ERROR, e);
41645
41780
  throw e;
41646
41781
  }
41647
41782
  }
@@ -41654,7 +41789,7 @@
41654
41789
  }));
41655
41790
  this._log(`interrupt ${this.joinUserId} ${result}`);
41656
41791
  } catch (e) {
41657
- this.dispatch('client.error', e);
41792
+ this.dispatch(event_handler_EventNames.ERROR, e);
41658
41793
  throw e;
41659
41794
  }
41660
41795
  }
@@ -41663,7 +41798,7 @@
41663
41798
  const result = await this.engine.sendUserMessage(this.joinUserId, JSON.stringify(message));
41664
41799
  this._log(`sendMessage ${this.joinUserId} ${JSON.stringify(message)} ${result}`);
41665
41800
  } catch (e) {
41666
- this.dispatch('client.error', e);
41801
+ this.dispatch(event_handler_EventNames.ERROR, e);
41667
41802
  throw e;
41668
41803
  }
41669
41804
  }
@@ -41704,7 +41839,7 @@
41704
41839
  try {
41705
41840
  await this.engine.startAudioPlaybackDeviceTest('audio-test.wav', 200);
41706
41841
  } catch (e) {
41707
- this.dispatch('client.error', e);
41842
+ this.dispatch(event_handler_EventNames.ERROR, e);
41708
41843
  throw e;
41709
41844
  }
41710
41845
  }
@@ -41712,12 +41847,13 @@
41712
41847
  try {
41713
41848
  this.engine.stopAudioPlaybackDeviceTest();
41714
41849
  } catch (e) {
41715
- this.dispatch('client.error', e);
41850
+ this.dispatch(event_handler_EventNames.ERROR, e);
41716
41851
  throw e;
41717
41852
  }
41718
41853
  }
41719
- constructor(appId, debug = false, isTestEnv = false){
41720
- super(debug), this.joinUserId = '', this._AIAnsExtension = null;
41854
+ // eslint-disable-next-line max-params
41855
+ constructor(appId, debug = false, isTestEnv = false, isSupportVideo = false){
41856
+ super(debug), this.joinUserId = '', this._AIAnsExtension = null, this._isSupportVideo = false;
41721
41857
  if (isTestEnv) index_esm_min_index.setParameter('ICE_CONFIG_REQUEST_URLS', [
41722
41858
  'rtc-test.bytedance.com'
41723
41859
  ]);
@@ -41726,9 +41862,11 @@
41726
41862
  this.handleUserJoin = this.handleUserJoin.bind(this);
41727
41863
  this.handleUserLeave = this.handleUserLeave.bind(this);
41728
41864
  this.handleEventError = this.handleEventError.bind(this);
41865
+ this.handlePlayerEvent = this.handlePlayerEvent.bind(this);
41729
41866
  // Debug only
41730
41867
  this.handleLocalAudioPropertiesReport = this.handleLocalAudioPropertiesReport.bind(this);
41731
41868
  this.handleRemoteAudioPropertiesReport = this.handleRemoteAudioPropertiesReport.bind(this);
41869
+ this._isSupportVideo = isSupportVideo;
41732
41870
  }
41733
41871
  }
41734
41872
  class RealtimeClient extends RealtimeEventHandler {
@@ -41737,6 +41875,7 @@
41737
41875
  *
41738
41876
  * zh: 建立与 Coze API 的连接并加入房间
41739
41877
  */ async connect() {
41878
+ var _this__config_videoConfig;
41740
41879
  const { botId, conversationId, voiceId } = this._config;
41741
41880
  let roomInfo;
41742
41881
  try {
@@ -41749,11 +41888,10 @@
41749
41888
  });
41750
41889
  } catch (error) {
41751
41890
  this.dispatch(event_handler_EventNames.ERROR, error);
41752
- throw new RealtimeAPIError(error_RealtimeError.CREATE_ROOM_ERROR, error instanceof Error ? error.message : 'Unknown error');
41891
+ throw new RealtimeAPIError(error_RealtimeError.CREATE_ROOM_ERROR, error instanceof Error ? error.message : 'Unknown error', error);
41753
41892
  }
41754
- this._roomInfo = roomInfo;
41755
41893
  // Step2 create engine
41756
- this._client = new EngineClient(roomInfo.app_id, this._config.debug, this._isTestEnv);
41894
+ this._client = new EngineClient(roomInfo.app_id, this._config.debug, this._isTestEnv, this._isSupportVideo);
41757
41895
  // Step3 bind engine events
41758
41896
  this._client.bindEngineEvents();
41759
41897
  this._client.on(event_handler_EventNames.ALL, (eventName, data)=>{
@@ -41768,16 +41906,17 @@
41768
41906
  this._client.changeAIAnsExtension(true);
41769
41907
  this.dispatch(event_handler_EventNames.SUPPRESS_NON_STATIONARY_NOISE, {});
41770
41908
  }
41771
- var _this__config_audioMutedDefault;
41909
+ var _this__config_audioMutedDefault, _this__config_videoConfig_videoOnDefault;
41772
41910
  // Step4 join room
41773
41911
  await this._client.joinRoom({
41774
41912
  token: roomInfo.token,
41775
41913
  roomId: roomInfo.room_id,
41776
41914
  uid: roomInfo.uid,
41777
- audioMutedDefault: null !== (_this__config_audioMutedDefault = this._config.audioMutedDefault) && void 0 !== _this__config_audioMutedDefault && _this__config_audioMutedDefault
41915
+ audioMutedDefault: null !== (_this__config_audioMutedDefault = this._config.audioMutedDefault) && void 0 !== _this__config_audioMutedDefault && _this__config_audioMutedDefault,
41916
+ 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
41778
41917
  });
41779
41918
  // Step5 create local stream
41780
- await this._client.createLocalStream();
41919
+ await this._client.createLocalStream(roomInfo.uid, this._config.videoConfig);
41781
41920
  // step6 set connected and dispatch connected event
41782
41921
  this.isConnected = true;
41783
41922
  this.dispatch(event_handler_EventNames.CONNECTED, {
@@ -41828,6 +41967,12 @@
41828
41967
  if (isEnable) this.dispatch(event_handler_EventNames.AUDIO_UNMUTED, {});
41829
41968
  else this.dispatch(event_handler_EventNames.AUDIO_MUTED, {});
41830
41969
  }
41970
+ async setVideoEnable(isEnable) {
41971
+ var _this__client;
41972
+ await (null === (_this__client = this._client) || void 0 === _this__client ? void 0 : _this__client.changeVideoState(isEnable));
41973
+ if (isEnable) this.dispatch(event_handler_EventNames.VIDEO_ON, {});
41974
+ else this.dispatch(event_handler_EventNames.VIDEO_OFF, {});
41975
+ }
41831
41976
  /**
41832
41977
  * en: Enable audio properties reporting (debug mode only)
41833
41978
  *
@@ -41913,7 +42058,7 @@
41913
42058
  * @param config.suppressNonStationaryNoise - Optional, suppress non-stationary noise, defaults to false. |
41914
42059
  * 可选,默认是否抑制非静态噪声,默认值为 false。
41915
42060
  */ constructor(config){
41916
- super(config.debug), this._client = null, this._roomInfo = null, this.isConnected = false, this._isTestEnv = false;
42061
+ super(config.debug), this._client = null, this.isConnected = false, this._isTestEnv = false, this._isSupportVideo = false;
41917
42062
  this._config = config;
41918
42063
  var _this__config_baseURL;
41919
42064
  const defaultBaseURL = null !== (_this__config_baseURL = this._config.baseURL) && void 0 !== _this__config_baseURL ? _this__config_baseURL : 'https://api.coze.cn';
@@ -41925,6 +42070,7 @@
41925
42070
  allowPersonalAccessTokenInBrowser: this._config.allowPersonalAccessTokenInBrowser
41926
42071
  });
41927
42072
  this._isTestEnv = 'https://api.coze.cn' !== defaultBaseURL;
42073
+ this._isSupportVideo = !!config.videoConfig;
41928
42074
  }
41929
42075
  }
41930
42076
  return __webpack_exports__;
package/package.json CHANGED
@@ -1,7 +1,18 @@
1
1
  {
2
2
  "name": "@coze/realtime-api",
3
- "version": "0.0.4",
4
- "description": "Coze Realtime API",
3
+ "version": "1.0.0",
4
+ "description": "A powerful real-time communication SDK for voice interactions with Coze AI bots | 扣子官方实时通信 SDK,用于与 Coze AI bots 进行语音交互",
5
+ "keywords": [
6
+ "coze",
7
+ "ai",
8
+ "realtime",
9
+ "voice",
10
+ "rtc",
11
+ "asr",
12
+ "tts",
13
+ "ai-agent",
14
+ "voice-synthesis"
15
+ ],
5
16
  "homepage": "https://github.com/coze-dev/coze-js/packages/realtime-api",
6
17
  "repository": {
7
18
  "type": "git",
@@ -40,7 +51,7 @@
40
51
  "test:cov": "vitest --coverage --run"
41
52
  },
42
53
  "dependencies": {
43
- "@coze/api": "1.0.8",
54
+ "@coze/api": "1.0.10",
44
55
  "@volcengine/rtc": "^4.62.1"
45
56
  },
46
57
  "devDependencies": {