@runanywhere/core 0.17.1 → 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.
Files changed (68) hide show
  1. package/android/src/main/include/rac/backends/rac_llm_llamacpp.h +218 -0
  2. package/android/src/main/include/rac/backends/rac_stt_onnx.h +99 -0
  3. package/android/src/main/include/rac/backends/rac_stt_whispercpp.h +153 -0
  4. package/android/src/main/include/rac/backends/rac_tts_onnx.h +71 -0
  5. package/android/src/main/include/rac/backends/rac_vad_onnx.h +84 -0
  6. package/android/src/main/include/rac/core/capabilities/rac_lifecycle.h +290 -0
  7. package/android/src/main/include/rac/core/rac_analytics_events.h +610 -0
  8. package/android/src/main/include/rac/core/rac_audio_utils.h +88 -0
  9. package/android/src/main/include/rac/core/rac_component_types.h +160 -0
  10. package/android/src/main/include/rac/core/rac_core.h +331 -0
  11. package/android/src/main/include/rac/core/rac_error.h +469 -0
  12. package/android/src/main/include/rac/core/rac_events.h +334 -0
  13. package/android/src/main/include/rac/core/rac_logger.h +416 -0
  14. package/android/src/main/include/rac/core/rac_platform_adapter.h +340 -0
  15. package/android/src/main/include/rac/core/rac_sdk_state.h +292 -0
  16. package/android/src/main/include/rac/core/rac_structured_error.h +594 -0
  17. package/android/src/main/include/rac/core/rac_types.h +264 -0
  18. package/android/src/main/include/rac/features/llm/rac_llm.h +17 -0
  19. package/android/src/main/include/rac/features/llm/rac_llm_analytics.h +188 -0
  20. package/android/src/main/include/rac/features/llm/rac_llm_component.h +228 -0
  21. package/android/src/main/include/rac/features/llm/rac_llm_events.h +215 -0
  22. package/android/src/main/include/rac/features/llm/rac_llm_metrics.h +402 -0
  23. package/android/src/main/include/rac/features/llm/rac_llm_service.h +163 -0
  24. package/android/src/main/include/rac/features/llm/rac_llm_structured_output.h +141 -0
  25. package/android/src/main/include/rac/features/llm/rac_llm_types.h +384 -0
  26. package/android/src/main/include/rac/features/platform/rac_llm_platform.h +204 -0
  27. package/android/src/main/include/rac/features/platform/rac_tts_platform.h +197 -0
  28. package/android/src/main/include/rac/features/stt/rac_stt.h +17 -0
  29. package/android/src/main/include/rac/features/stt/rac_stt_analytics.h +204 -0
  30. package/android/src/main/include/rac/features/stt/rac_stt_component.h +162 -0
  31. package/android/src/main/include/rac/features/stt/rac_stt_events.h +62 -0
  32. package/android/src/main/include/rac/features/stt/rac_stt_service.h +154 -0
  33. package/android/src/main/include/rac/features/stt/rac_stt_types.h +389 -0
  34. package/android/src/main/include/rac/features/tts/rac_tts.h +17 -0
  35. package/android/src/main/include/rac/features/tts/rac_tts_analytics.h +181 -0
  36. package/android/src/main/include/rac/features/tts/rac_tts_component.h +158 -0
  37. package/android/src/main/include/rac/features/tts/rac_tts_events.h +54 -0
  38. package/android/src/main/include/rac/features/tts/rac_tts_service.h +162 -0
  39. package/android/src/main/include/rac/features/tts/rac_tts_types.h +374 -0
  40. package/android/src/main/include/rac/features/vad/rac_vad.h +17 -0
  41. package/android/src/main/include/rac/features/vad/rac_vad_analytics.h +236 -0
  42. package/android/src/main/include/rac/features/vad/rac_vad_component.h +185 -0
  43. package/android/src/main/include/rac/features/vad/rac_vad_energy.h +443 -0
  44. package/android/src/main/include/rac/features/vad/rac_vad_events.h +76 -0
  45. package/android/src/main/include/rac/features/vad/rac_vad_service.h +167 -0
  46. package/android/src/main/include/rac/features/vad/rac_vad_types.h +244 -0
  47. package/android/src/main/include/rac/features/voice_agent/rac_voice_agent.h +612 -0
  48. package/android/src/main/include/rac/infrastructure/device/rac_device_manager.h +176 -0
  49. package/android/src/main/include/rac/infrastructure/download/rac_download.h +418 -0
  50. package/android/src/main/include/rac/infrastructure/events/rac_events.h +177 -0
  51. package/android/src/main/include/rac/infrastructure/model_management/rac_model_assignment.h +169 -0
  52. package/android/src/main/include/rac/infrastructure/model_management/rac_model_paths.h +258 -0
  53. package/android/src/main/include/rac/infrastructure/model_management/rac_model_registry.h +357 -0
  54. package/android/src/main/include/rac/infrastructure/model_management/rac_model_strategy.h +374 -0
  55. package/android/src/main/include/rac/infrastructure/model_management/rac_model_types.h +613 -0
  56. package/android/src/main/include/rac/infrastructure/network/rac_api_types.h +335 -0
  57. package/android/src/main/include/rac/infrastructure/network/rac_auth_manager.h +252 -0
  58. package/android/src/main/include/rac/infrastructure/network/rac_dev_config.h +85 -0
  59. package/android/src/main/include/rac/infrastructure/network/rac_endpoints.h +102 -0
  60. package/android/src/main/include/rac/infrastructure/network/rac_environment.h +220 -0
  61. package/android/src/main/include/rac/infrastructure/network/rac_http_client.h +233 -0
  62. package/android/src/main/include/rac/infrastructure/storage/rac_storage_analyzer.h +286 -0
  63. package/android/src/main/include/rac/infrastructure/telemetry/rac_telemetry_manager.h +206 -0
  64. package/android/src/main/include/rac/infrastructure/telemetry/rac_telemetry_types.h +234 -0
  65. package/package.json +1 -1
  66. package/src/Features/VoiceSession/AudioCaptureManager.ts +33 -3
  67. package/src/Features/VoiceSession/AudioPlaybackManager.ts +22 -7
  68. package/src/Features/VoiceSession/VoiceSessionHandle.ts +41 -12
@@ -0,0 +1,234 @@
1
+ /**
2
+ * @file rac_telemetry_types.h
3
+ * @brief Telemetry data structures - canonical source of truth
4
+ *
5
+ * All telemetry payloads are defined here. Platform SDKs (Swift, Kotlin, Flutter)
6
+ * use these types directly or create thin wrappers.
7
+ *
8
+ * Mirrors Swift's TelemetryEventPayload.swift structure.
9
+ */
10
+
11
+ #ifndef RAC_TELEMETRY_TYPES_H
12
+ #define RAC_TELEMETRY_TYPES_H
13
+
14
+ #include "rac/core/rac_types.h"
15
+ #include "rac/infrastructure/network/rac_environment.h"
16
+
17
+ #ifdef __cplusplus
18
+ extern "C" {
19
+ #endif
20
+
21
+ // =============================================================================
22
+ // TELEMETRY EVENT PAYLOAD
23
+ // =============================================================================
24
+
25
+ /**
26
+ * @brief Complete telemetry event payload
27
+ *
28
+ * Maps to backend SDKTelemetryEvent schema with all fields for:
29
+ * - LLM events (tokens, generation times, etc.)
30
+ * - STT events (audio duration, word count, etc.)
31
+ * - TTS events (character count, audio size, etc.)
32
+ * - VAD events (speech duration)
33
+ * - Model lifecycle events (size, archive type)
34
+ * - SDK lifecycle events (count)
35
+ * - Storage events (freed bytes)
36
+ * - Network events (online status)
37
+ */
38
+ typedef struct rac_telemetry_payload {
39
+ // Required fields
40
+ const char* id; // Unique event ID (UUID)
41
+ const char* event_type; // Event type string
42
+ int64_t timestamp_ms; // Unix timestamp in milliseconds
43
+ int64_t created_at_ms; // When payload was created
44
+
45
+ // Event classification
46
+ const char* modality; // "llm", "stt", "tts", "model", "system"
47
+
48
+ // Device identification
49
+ const char* device_id; // Persistent device UUID
50
+ const char* session_id; // Optional session ID
51
+
52
+ // Model info
53
+ const char* model_id;
54
+ const char* model_name;
55
+ const char* framework; // "llamacpp", "onnx", "mlx", etc.
56
+
57
+ // Device info
58
+ const char* device; // Device model (e.g., "iPhone15,2")
59
+ const char* os_version; // OS version (e.g., "17.0")
60
+ const char* platform; // "ios", "android", "flutter"
61
+ const char* sdk_version; // SDK version string
62
+
63
+ // Common performance metrics
64
+ double processing_time_ms;
65
+ rac_bool_t success;
66
+ rac_bool_t has_success; // Whether success field is set
67
+ const char* error_message;
68
+ const char* error_code;
69
+
70
+ // LLM-specific fields
71
+ int32_t input_tokens;
72
+ int32_t output_tokens;
73
+ int32_t total_tokens;
74
+ double tokens_per_second;
75
+ double time_to_first_token_ms;
76
+ double prompt_eval_time_ms;
77
+ double generation_time_ms;
78
+ int32_t context_length;
79
+ double temperature;
80
+ int32_t max_tokens;
81
+
82
+ // STT-specific fields
83
+ double audio_duration_ms;
84
+ double real_time_factor;
85
+ int32_t word_count;
86
+ double confidence;
87
+ const char* language;
88
+ rac_bool_t is_streaming;
89
+ rac_bool_t has_is_streaming;
90
+ int32_t segment_index;
91
+
92
+ // TTS-specific fields
93
+ int32_t character_count;
94
+ double characters_per_second;
95
+ int32_t audio_size_bytes;
96
+ int32_t sample_rate;
97
+ const char* voice;
98
+ double output_duration_ms;
99
+
100
+ // Model lifecycle fields
101
+ int64_t model_size_bytes;
102
+ const char* archive_type;
103
+
104
+ // VAD fields
105
+ double speech_duration_ms;
106
+
107
+ // SDK lifecycle fields
108
+ int32_t count;
109
+
110
+ // Storage fields
111
+ int64_t freed_bytes;
112
+
113
+ // Network fields
114
+ rac_bool_t is_online;
115
+ rac_bool_t has_is_online;
116
+ } rac_telemetry_payload_t;
117
+
118
+ /**
119
+ * @brief Default/empty telemetry payload
120
+ */
121
+ RAC_API rac_telemetry_payload_t rac_telemetry_payload_default(void);
122
+
123
+ /**
124
+ * @brief Free any allocated strings in a telemetry payload
125
+ */
126
+ RAC_API void rac_telemetry_payload_free(rac_telemetry_payload_t* payload);
127
+
128
+ // =============================================================================
129
+ // TELEMETRY BATCH REQUEST
130
+ // =============================================================================
131
+
132
+ /**
133
+ * @brief Batch telemetry request for API
134
+ *
135
+ * Supports both V1 and V2 storage paths:
136
+ * - V1 (legacy): modality = NULL → stores in sdk_telemetry_events table
137
+ * - V2 (normalized): modality = "llm"/"stt"/"tts"/"model" → normalized tables
138
+ */
139
+ typedef struct rac_telemetry_batch_request {
140
+ rac_telemetry_payload_t* events;
141
+ size_t events_count;
142
+ const char* device_id;
143
+ int64_t timestamp_ms;
144
+ const char* modality; // NULL for V1, "llm"/"stt"/"tts"/"model" for V2
145
+ } rac_telemetry_batch_request_t;
146
+
147
+ /**
148
+ * @brief Batch telemetry response from API
149
+ */
150
+ typedef struct rac_telemetry_batch_response {
151
+ rac_bool_t success;
152
+ int32_t events_received;
153
+ int32_t events_stored;
154
+ int32_t events_skipped; // Duplicates skipped
155
+ const char** errors; // Array of error messages
156
+ size_t errors_count;
157
+ const char* storage_version; // "V1" or "V2"
158
+ } rac_telemetry_batch_response_t;
159
+
160
+ /**
161
+ * @brief Free batch response
162
+ */
163
+ RAC_API void rac_telemetry_batch_response_free(rac_telemetry_batch_response_t* response);
164
+
165
+ // =============================================================================
166
+ // DEVICE REGISTRATION TYPES
167
+ // =============================================================================
168
+
169
+ /**
170
+ * @brief Device information for registration (telemetry-specific)
171
+ *
172
+ * Platform-specific values are passed in from Swift/Kotlin.
173
+ * Matches backend schemas/device.py DeviceInfo schema.
174
+ * Note: Named differently from rac_device_info_t to avoid conflict.
175
+ */
176
+ typedef struct rac_device_registration_info {
177
+ // Required fields (backend schema)
178
+ const char* device_id; // Persistent UUID from Keychain/secure storage
179
+ const char* device_model; // "iPhone 16 Pro Max", "Pixel 7", etc.
180
+ const char* device_name; // User-assigned device name
181
+ const char* platform; // "ios", "android"
182
+ const char* os_version; // "17.0", "14"
183
+ const char* form_factor; // "phone", "tablet", "laptop", etc.
184
+ const char* architecture; // "arm64", "x86_64", etc.
185
+ const char* chip_name; // "A18 Pro", "Snapdragon 888", etc.
186
+ int64_t total_memory; // Total RAM in bytes
187
+ int64_t available_memory; // Available RAM in bytes
188
+ rac_bool_t has_neural_engine; // true if device has Neural Engine / NPU
189
+ int32_t neural_engine_cores; // Number of Neural Engine cores (0 if none)
190
+ const char* gpu_family; // "apple", "adreno", etc.
191
+ double battery_level; // 0.0-1.0, negative if unavailable
192
+ const char* battery_state; // "charging", "full", "unplugged", NULL if unavailable
193
+ rac_bool_t is_low_power_mode; // Low power mode enabled
194
+ int32_t core_count; // Total CPU cores
195
+ int32_t performance_cores; // Performance (P) cores
196
+ int32_t efficiency_cores; // Efficiency (E) cores
197
+ const char* device_fingerprint; // Unique device fingerprint (may be same as device_id)
198
+
199
+ // Legacy fields (for backward compatibility)
200
+ const char* device_type; // "smartphone", "tablet", etc. (deprecated - use form_factor)
201
+ const char* os_name; // "iOS", "Android" (deprecated - use platform)
202
+ int64_t total_disk_bytes;
203
+ int64_t available_disk_bytes;
204
+ const char* processor_info;
205
+ int32_t processor_count; // Deprecated - use core_count
206
+ rac_bool_t is_simulator;
207
+ const char* locale;
208
+ const char* timezone;
209
+ } rac_device_registration_info_t;
210
+
211
+ /**
212
+ * @brief Device registration request
213
+ */
214
+ typedef struct rac_device_registration_request {
215
+ rac_device_registration_info_t device_info;
216
+ const char* sdk_version;
217
+ const char* build_token; // For development mode
218
+ int64_t last_seen_at_ms;
219
+ } rac_device_registration_request_t;
220
+
221
+ /**
222
+ * @brief Device registration response
223
+ */
224
+ typedef struct rac_device_registration_response {
225
+ const char* device_id;
226
+ const char* status; // "registered" or "updated"
227
+ const char* sync_status; // "synced" or "pending"
228
+ } rac_device_registration_response_t;
229
+
230
+ #ifdef __cplusplus
231
+ }
232
+ #endif
233
+
234
+ #endif // RAC_TELEMETRY_TYPES_H
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@runanywhere/core",
3
- "version": "0.17.1",
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
  }