@runanywhere/core 0.17.2 → 0.17.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runanywhere/core",
3
- "version": "0.17.2",
3
+ "version": "0.17.3",
4
4
  "description": "Core SDK for RunAnywhere React Native - includes RACommons bindings, native bridges, and public API",
5
5
  "main": "src/index.ts",
6
6
  "types": "src/index.ts",
@@ -8,11 +8,41 @@
8
8
  */
9
9
 
10
10
  import { Platform, PermissionsAndroid, NativeModules } from 'react-native';
11
- import { EventBus } from '../../Public/Events';
12
11
  import { SDKLogger } from '../../Foundation/Logging/Logger/SDKLogger';
13
12
 
14
13
  const logger = new SDKLogger('AudioCaptureManager');
15
14
 
15
+ // Lazy-load EventBus to avoid circular dependency issues during module initialization
16
+ // The circular dependency: AudioCaptureManager -> EventBus -> SDKLogger -> ... -> AudioCaptureManager
17
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
18
+ let _eventBus: any = null;
19
+ function getEventBus() {
20
+ if (!_eventBus) {
21
+ try {
22
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
23
+ _eventBus = require('../../Public/Events').EventBus;
24
+ } catch {
25
+ logger.warning('EventBus not available');
26
+ }
27
+ }
28
+ return _eventBus;
29
+ }
30
+
31
+ /**
32
+ * Safely publish an event to the EventBus
33
+ * Handles cases where EventBus may not be fully initialized
34
+ */
35
+ function safePublish(eventType: string, event: Record<string, unknown>): void {
36
+ try {
37
+ const eventBus = getEventBus();
38
+ if (eventBus?.publish) {
39
+ eventBus.publish(eventType, event);
40
+ }
41
+ } catch {
42
+ // Ignore EventBus errors - events are non-critical for audio functionality
43
+ }
44
+ }
45
+
16
46
  // Native iOS Audio Module (provided by the app)
17
47
  const NativeAudioModule = Platform.OS === 'ios' ? NativeModules.NativeAudioModule : null;
18
48
 
@@ -156,7 +186,7 @@ export class AudioCaptureManager {
156
186
  this.state = 'recording';
157
187
 
158
188
  logger.info('Starting audio recording...');
159
- EventBus.publish('Voice', { type: 'recordingStarted' });
189
+ safePublish('Voice', { type: 'recordingStarted' });
160
190
 
161
191
  if (Platform.OS === 'ios') {
162
192
  await this.startIOSRecording();
@@ -186,7 +216,7 @@ export class AudioCaptureManager {
186
216
  path = await this.stopAndroidRecording();
187
217
  }
188
218
 
189
- EventBus.publish('Voice', { type: 'recordingStopped', duration: durationMs / 1000 });
219
+ safePublish('Voice', { type: 'recordingStopped', duration: durationMs / 1000 });
190
220
 
191
221
  this.audioDataCallback = null;
192
222
  this.recordingStartTime = null;
@@ -8,11 +8,26 @@
8
8
  */
9
9
 
10
10
  import { Platform, NativeModules } from 'react-native';
11
- import { EventBus } from '../../Public/Events';
12
11
  import { SDKLogger } from '../../Foundation/Logging/Logger/SDKLogger';
13
12
 
14
13
  const logger = new SDKLogger('AudioPlaybackManager');
15
14
 
15
+ /**
16
+ * Safely publish an event to the EventBus
17
+ * Uses lazy loading to avoid circular dependency issues during module initialization
18
+ */
19
+ function safePublish(eventType: string, event: Record<string, unknown>): void {
20
+ try {
21
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
22
+ const { EventBus } = require('../../Public/Events');
23
+ if (EventBus?.publish) {
24
+ EventBus.publish(eventType, event);
25
+ }
26
+ } catch {
27
+ // Ignore EventBus errors - events are non-critical for playback functionality
28
+ }
29
+ }
30
+
16
31
  // Native iOS Audio Module
17
32
  const NativeAudioModule = Platform.OS === 'ios' ? NativeModules.NativeAudioModule : null;
18
33
 
@@ -151,7 +166,7 @@ export class AudioPlaybackManager {
151
166
  this.state = 'error';
152
167
  const err = error instanceof Error ? error : new Error(String(error));
153
168
  logger.error(`Playback failed: ${err.message}`);
154
- EventBus.publish('Voice', { type: 'playbackFailed', error: err.message });
169
+ safePublish('Voice', { type: 'playbackFailed', error: err.message });
155
170
 
156
171
  if (this.errorCallback) {
157
172
  this.errorCallback(err);
@@ -168,7 +183,7 @@ export class AudioPlaybackManager {
168
183
  this.state = 'playing';
169
184
 
170
185
  logger.info(`Playing audio file: ${filePath}`);
171
- EventBus.publish('Voice', { type: 'playbackStarted' });
186
+ safePublish('Voice', { type: 'playbackStarted' });
172
187
 
173
188
  if (Platform.OS === 'ios') {
174
189
  await this.playFileIOS(filePath);
@@ -196,7 +211,7 @@ export class AudioPlaybackManager {
196
211
  this.currentSound = null;
197
212
  }
198
213
 
199
- EventBus.publish('Voice', { type: 'playbackStopped' });
214
+ safePublish('Voice', { type: 'playbackStopped' });
200
215
 
201
216
  if (this.completionCallback) {
202
217
  this.completionCallback();
@@ -217,7 +232,7 @@ export class AudioPlaybackManager {
217
232
  }
218
233
 
219
234
  logger.info('Playback paused');
220
- EventBus.publish('Voice', { type: 'playbackPaused' });
235
+ safePublish('Voice', { type: 'playbackPaused' });
221
236
  }
222
237
  }
223
238
 
@@ -235,7 +250,7 @@ export class AudioPlaybackManager {
235
250
  }
236
251
 
237
252
  logger.info('Playback resumed');
238
- EventBus.publish('Voice', { type: 'playbackResumed' });
253
+ safePublish('Voice', { type: 'playbackResumed' });
239
254
  }
240
255
  }
241
256
 
@@ -389,7 +404,7 @@ export class AudioPlaybackManager {
389
404
 
390
405
  logger.info(`Playback completed (${duration.toFixed(2)}s)`);
391
406
 
392
- EventBus.publish('Voice', {
407
+ safePublish('Voice', {
393
408
  type: 'playbackCompleted',
394
409
  duration,
395
410
  });
@@ -28,9 +28,38 @@
28
28
  * ```
29
29
  */
30
30
 
31
- import { EventBus } from '../../Public/Events';
32
31
  import { SDKLogger } from '../../Foundation/Logging/Logger/SDKLogger';
33
32
  import { AudioCaptureManager } from './AudioCaptureManager';
33
+
34
+ // Lazy-load EventBus to avoid circular dependency issues during module initialization
35
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
+ let _eventBus: any = null;
37
+ function getEventBus() {
38
+ if (!_eventBus) {
39
+ try {
40
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
41
+ _eventBus = require('../../Public/Events').EventBus;
42
+ } catch {
43
+ // EventBus not available
44
+ }
45
+ }
46
+ return _eventBus;
47
+ }
48
+
49
+ /**
50
+ * Safely publish an event to the EventBus
51
+ * Handles cases where EventBus may not be fully initialized due to circular dependencies
52
+ */
53
+ function safePublish(eventType: string, event: Record<string, unknown>): void {
54
+ try {
55
+ const eventBus = getEventBus();
56
+ if (eventBus?.publish) {
57
+ eventBus.publish(eventType, event);
58
+ }
59
+ } catch {
60
+ // Ignore EventBus errors - events are non-critical for voice session functionality
61
+ }
62
+ }
34
63
  import { AudioPlaybackManager } from './AudioPlaybackManager';
35
64
  import * as STT from '../../Public/Extensions/RunAnywhere+STT';
36
65
  import * as TextGeneration from '../../Public/Extensions/RunAnywhere+TextGeneration';
@@ -390,31 +419,31 @@ export class VoiceSessionHandle {
390
419
 
391
420
  switch (eventBusType) {
392
421
  case 'voiceSession_started':
393
- EventBus.publish('Voice', { type: 'voiceSession_started' });
422
+ safePublish('Voice', { type: 'voiceSession_started' });
394
423
  break;
395
424
  case 'voiceSession_listening':
396
- EventBus.publish('Voice', { type: 'voiceSession_listening', audioLevel: eventData.audioLevel });
425
+ safePublish('Voice', { type: 'voiceSession_listening', audioLevel: eventData.audioLevel });
397
426
  break;
398
427
  case 'voiceSession_speechStarted':
399
- EventBus.publish('Voice', { type: 'voiceSession_speechStarted' });
428
+ safePublish('Voice', { type: 'voiceSession_speechStarted' });
400
429
  break;
401
430
  case 'voiceSession_speechEnded':
402
- EventBus.publish('Voice', { type: 'voiceSession_speechEnded' });
431
+ safePublish('Voice', { type: 'voiceSession_speechEnded' });
403
432
  break;
404
433
  case 'voiceSession_processing':
405
- EventBus.publish('Voice', { type: 'voiceSession_processing' });
434
+ safePublish('Voice', { type: 'voiceSession_processing' });
406
435
  break;
407
436
  case 'voiceSession_transcribed':
408
- EventBus.publish('Voice', { type: 'voiceSession_transcribed', transcription: eventData.transcription });
437
+ safePublish('Voice', { type: 'voiceSession_transcribed', transcription: eventData.transcription });
409
438
  break;
410
439
  case 'voiceSession_responded':
411
- EventBus.publish('Voice', { type: 'voiceSession_responded', response: eventData.response });
440
+ safePublish('Voice', { type: 'voiceSession_responded', response: eventData.response });
412
441
  break;
413
442
  case 'voiceSession_speaking':
414
- EventBus.publish('Voice', { type: 'voiceSession_speaking' });
443
+ safePublish('Voice', { type: 'voiceSession_speaking' });
415
444
  break;
416
445
  case 'voiceSession_turnCompleted':
417
- EventBus.publish('Voice', {
446
+ safePublish('Voice', {
418
447
  type: 'voiceSession_turnCompleted',
419
448
  transcription: eventData.transcription,
420
449
  response: eventData.response,
@@ -422,10 +451,10 @@ export class VoiceSessionHandle {
422
451
  });
423
452
  break;
424
453
  case 'voiceSession_stopped':
425
- EventBus.publish('Voice', { type: 'voiceSession_stopped' });
454
+ safePublish('Voice', { type: 'voiceSession_stopped' });
426
455
  break;
427
456
  case 'voiceSession_error':
428
- EventBus.publish('Voice', { type: 'voiceSession_error', error: eventData.error });
457
+ safePublish('Voice', { type: 'voiceSession_error', error: eventData.error });
429
458
  break;
430
459
  }
431
460
  }