@mentra/sdk 1.1.19 → 2.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/README.md +4 -4
- package/dist/{tpa → app}/index.d.ts.map +1 -1
- package/dist/{tpa → app}/index.js +2 -2
- package/dist/{tpa → app}/server/index.d.ts +21 -21
- package/dist/app/server/index.d.ts.map +1 -0
- package/dist/{tpa → app}/server/index.js +21 -21
- package/dist/{tpa → app}/session/api-client.d.ts +1 -1
- package/dist/{tpa → app}/session/api-client.d.ts.map +1 -1
- package/dist/{tpa → app}/session/api-client.js +2 -2
- package/dist/{tpa → app}/session/dashboard.d.ts +9 -9
- package/dist/{tpa → app}/session/dashboard.d.ts.map +1 -1
- package/dist/{tpa → app}/session/dashboard.js +10 -10
- package/dist/{tpa → app}/session/events.d.ts +1 -1
- package/dist/{tpa → app}/session/events.d.ts.map +1 -1
- package/dist/{tpa → app}/session/events.js +1 -1
- package/dist/{tpa → app}/session/index.d.ts +40 -38
- package/dist/app/session/index.d.ts.map +1 -0
- package/dist/{tpa → app}/session/index.js +126 -116
- package/dist/{tpa → app}/session/layouts.d.ts +2 -2
- package/dist/{tpa → app}/session/layouts.d.ts.map +1 -1
- package/dist/{tpa → app}/session/layouts.js +4 -4
- package/dist/{tpa → app}/session/modules/streaming.d.ts +5 -5
- package/dist/{tpa → app}/session/modules/streaming.d.ts.map +1 -1
- package/dist/{tpa → app}/session/modules/streaming.js +7 -7
- package/dist/{tpa → app}/session/settings.d.ts +3 -3
- package/dist/{tpa → app}/session/settings.d.ts.map +1 -1
- package/dist/{tpa → app}/session/settings.js +5 -7
- package/dist/app/token/index.d.ts +7 -0
- package/dist/app/token/index.d.ts.map +1 -0
- package/dist/{tpa → app}/token/index.js +2 -2
- package/dist/{tpa → app}/token/utils.d.ts +6 -6
- package/dist/{tpa → app}/token/utils.d.ts.map +1 -1
- package/dist/{tpa → app}/token/utils.js +6 -6
- package/dist/{tpa → app}/webview/index.d.ts +3 -3
- package/dist/{tpa → app}/webview/index.d.ts.map +1 -1
- package/dist/{tpa → app}/webview/index.js +4 -4
- package/dist/examples/rtmp-streaming-example.js +6 -6
- package/dist/index.d.ts +39 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +76 -16
- package/dist/types/capabilities.d.ts +92 -0
- package/dist/types/capabilities.d.ts.map +1 -0
- package/dist/types/capabilities.js +9 -0
- package/dist/types/dashboard/index.d.ts +9 -9
- package/dist/types/enums.d.ts +2 -2
- package/dist/types/enums.js +8 -8
- package/dist/types/index.d.ts +7 -6
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +26 -24
- package/dist/types/layouts.d.ts +2 -2
- package/dist/types/message-types.d.ts +18 -18
- package/dist/types/message-types.js +47 -47
- package/dist/types/messages/app-to-cloud.d.ts +146 -0
- package/dist/types/messages/{tpa-to-cloud.d.ts.map → app-to-cloud.d.ts.map} +1 -1
- package/dist/types/messages/{tpa-to-cloud.js → app-to-cloud.js} +18 -18
- package/dist/types/messages/{cloud-to-tpa.d.ts → cloud-to-app.d.ts} +54 -52
- package/dist/types/messages/cloud-to-app.d.ts.map +1 -0
- package/dist/types/messages/{cloud-to-tpa.js → cloud-to-app.js} +22 -22
- package/dist/types/models.d.ts +7 -7
- package/dist/types/models.js +3 -3
- package/dist/types/streams.d.ts +2 -2
- package/dist/types/streams.js +2 -2
- package/dist/types/token.d.ts +7 -7
- package/dist/types/token.js +2 -2
- package/dist/types/webhooks.d.ts +8 -8
- package/dist/types/webhooks.js +3 -3
- package/package.json +2 -1
- package/dist/tpa/server/index.d.ts.map +0 -1
- package/dist/tpa/session/index.d.ts.map +0 -1
- package/dist/tpa/token/index.d.ts +0 -7
- package/dist/tpa/token/index.d.ts.map +0 -1
- package/dist/types/messages/cloud-to-tpa.d.ts.map +0 -1
- package/dist/types/messages/tpa-to-cloud.d.ts +0 -146
- /package/dist/{tpa → app}/index.d.ts +0 -0
@@ -3,9 +3,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
-
exports.
|
6
|
+
exports.AppSession = void 0;
|
7
7
|
/**
|
8
|
-
* 🎯
|
8
|
+
* 🎯 App Session Module
|
9
9
|
*
|
10
10
|
* Manages an active Third Party App session with AugmentOS Cloud.
|
11
11
|
* Handles real-time communication, event subscriptions, and display management.
|
@@ -19,20 +19,20 @@ const resource_tracker_1 = require("../../utils/resource-tracker");
|
|
19
19
|
const types_1 = require("../../types");
|
20
20
|
const axios_1 = __importDefault(require("axios"));
|
21
21
|
const events_2 = __importDefault(require("events"));
|
22
|
-
// Import the cloud-to-
|
23
|
-
const
|
22
|
+
// Import the cloud-to-app specific type guards
|
23
|
+
const cloud_to_app_1 = require("../../types/messages/cloud-to-app");
|
24
24
|
// List of event types that should never be subscribed to as streams
|
25
|
-
const
|
26
|
-
'
|
27
|
-
'
|
28
|
-
'
|
29
|
-
'
|
30
|
-
'
|
25
|
+
const APP_TO_APP_EVENT_TYPES = [
|
26
|
+
'app_message_received',
|
27
|
+
'app_user_joined',
|
28
|
+
'app_user_left',
|
29
|
+
'app_room_updated',
|
30
|
+
'app_direct_message_response'
|
31
31
|
];
|
32
32
|
/**
|
33
|
-
* 🚀
|
33
|
+
* 🚀 App Session Implementation
|
34
34
|
*
|
35
|
-
* Manages a live connection between your
|
35
|
+
* Manages a live connection between your App and AugmentOS Cloud.
|
36
36
|
* Provides interfaces for:
|
37
37
|
* - 🎮 Event handling (transcription, head position, etc.)
|
38
38
|
* - 📱 Display management in AR view
|
@@ -41,7 +41,7 @@ const TPA_TO_TPA_EVENT_TYPES = [
|
|
41
41
|
*
|
42
42
|
* @example
|
43
43
|
* ```typescript
|
44
|
-
* const session = new
|
44
|
+
* const session = new AppSession({
|
45
45
|
* packageName: 'org.example.myapp',
|
46
46
|
* apiKey: 'your_api_key'
|
47
47
|
* });
|
@@ -55,7 +55,7 @@ const TPA_TO_TPA_EVENT_TYPES = [
|
|
55
55
|
* await session.connect('session_123');
|
56
56
|
* ```
|
57
57
|
*/
|
58
|
-
class
|
58
|
+
class AppSession {
|
59
59
|
constructor(config) {
|
60
60
|
this.config = config;
|
61
61
|
/** WebSocket connection to AugmentOS Cloud */
|
@@ -70,8 +70,8 @@ class TpaSession {
|
|
70
70
|
this.resources = new resource_tracker_1.ResourceTracker();
|
71
71
|
/** Internal settings storage - use public settings API instead */
|
72
72
|
this.settingsData = [];
|
73
|
-
/**
|
74
|
-
this.
|
73
|
+
/** App configuration loaded from app_config.json */
|
74
|
+
this.appConfig = null;
|
75
75
|
/** Whether to update subscriptions when settings change */
|
76
76
|
this.shouldUpdateSubscriptionsOnSettingsChange = false;
|
77
77
|
/** Settings that should trigger subscription updates when changed */
|
@@ -82,18 +82,20 @@ class TpaSession {
|
|
82
82
|
this.pendingUserDiscoveryRequests = new Map();
|
83
83
|
/** Pending direct message requests waiting for responses */
|
84
84
|
this.pendingDirectMessages = new Map();
|
85
|
-
/**
|
86
|
-
this.
|
85
|
+
/** 🔧 Device capabilities available for this session */
|
86
|
+
this.capabilities = null;
|
87
|
+
/** Dedicated emitter for App-to-App events */
|
88
|
+
this.appEvents = new events_2.default();
|
87
89
|
// Set defaults and merge with provided config
|
88
90
|
this.config = {
|
89
|
-
augmentOSWebsocketUrl: `ws://localhost:8002/
|
91
|
+
augmentOSWebsocketUrl: `ws://localhost:8002/app-ws`, // Use localhost as default
|
90
92
|
autoReconnect: true, // Enable auto-reconnection by default for better reliability
|
91
93
|
maxReconnectAttempts: 3, // Default to 3 reconnection attempts for better resilience
|
92
94
|
reconnectDelay: 1000, // Start with 1 second delay (uses exponential backoff)
|
93
95
|
...config
|
94
96
|
};
|
95
|
-
this.
|
96
|
-
this.logger = this.
|
97
|
+
this.appServer = this.config.appServer;
|
98
|
+
this.logger = this.appServer.logger.child({ userId: this.config.userId, service: 'app-session' });
|
97
99
|
this.userId = this.config.userId;
|
98
100
|
// Make sure the URL is correctly formatted to prevent double protocol issues
|
99
101
|
if (this.config.augmentOSWebsocketUrl) {
|
@@ -111,7 +113,7 @@ class TpaSession {
|
|
111
113
|
}
|
112
114
|
}
|
113
115
|
// Log initialization
|
114
|
-
this.logger.debug(`🚀 [${this.config.packageName}]
|
116
|
+
this.logger.debug(`🚀 [${this.config.packageName}] App Session initialized`);
|
115
117
|
this.logger.debug(`🚀 [${this.config.packageName}] WebSocket URL: ${this.config.augmentOSWebsocketUrl}`);
|
116
118
|
// Validate URL format - give early warning for obvious issues
|
117
119
|
// Check URL format but handle undefined case
|
@@ -130,23 +132,23 @@ class TpaSession {
|
|
130
132
|
this.layouts = new layouts_1.LayoutManager(config.packageName, this.send.bind(this));
|
131
133
|
// Initialize settings manager with all necessary parameters, including subscribeFn for AugmentOS settings
|
132
134
|
this.settings = new settings_1.SettingsManager(this.settingsData, this.config.packageName, this.config.augmentOSWebsocketUrl, this.sessionId ?? undefined, async (streams) => {
|
133
|
-
this.logger.debug(`[
|
135
|
+
this.logger.debug(`[AppSession] subscribeFn called for streams:`, streams);
|
134
136
|
streams.forEach((stream) => {
|
135
137
|
if (!this.subscriptions.has(stream)) {
|
136
138
|
this.subscriptions.add(stream);
|
137
|
-
this.logger.debug(`[
|
139
|
+
this.logger.debug(`[AppSession] Auto-subscribed to stream '${stream}' for AugmentOS setting.`);
|
138
140
|
}
|
139
141
|
else {
|
140
|
-
this.logger.debug(`[
|
142
|
+
this.logger.debug(`[AppSession] Already subscribed to stream '${stream}'.`);
|
141
143
|
}
|
142
144
|
});
|
143
|
-
this.logger.debug(`[
|
145
|
+
this.logger.debug(`[AppSession] Current subscriptions after subscribeFn:`, Array.from(this.subscriptions));
|
144
146
|
if (this.ws?.readyState === 1) {
|
145
147
|
this.updateSubscriptions();
|
146
|
-
this.logger.debug(`[
|
148
|
+
this.logger.debug(`[AppSession] Sent updated subscriptions to cloud after auto-subscribing to AugmentOS setting.`);
|
147
149
|
}
|
148
150
|
else {
|
149
|
-
this.logger.debug(`[
|
151
|
+
this.logger.debug(`[AppSession] WebSocket not open, will send subscriptions when connected.`);
|
150
152
|
}
|
151
153
|
});
|
152
154
|
// Initialize dashboard API with this session instance
|
@@ -165,7 +167,7 @@ class TpaSession {
|
|
165
167
|
return this.sessionId || 'unknown-session-id';
|
166
168
|
}
|
167
169
|
/**
|
168
|
-
* Get the package name for this
|
170
|
+
* Get the package name for this App
|
169
171
|
* @returns The package name
|
170
172
|
*/
|
171
173
|
getPackageName() {
|
@@ -253,8 +255,8 @@ class TpaSession {
|
|
253
255
|
* @param type - Type of event to subscribe to
|
254
256
|
*/
|
255
257
|
subscribe(type) {
|
256
|
-
if (
|
257
|
-
this.logger.warn(`[
|
258
|
+
if (APP_TO_APP_EVENT_TYPES.includes(type)) {
|
259
|
+
this.logger.warn(`[AppSession] Attempted to subscribe to App-to-App event type '${type}', which is not a valid stream. Use the event handler (e.g., onAppMessage) instead.`);
|
258
260
|
return;
|
259
261
|
}
|
260
262
|
this.subscriptions.add(type);
|
@@ -267,8 +269,8 @@ class TpaSession {
|
|
267
269
|
* @param type - Type of event to unsubscribe from
|
268
270
|
*/
|
269
271
|
unsubscribe(type) {
|
270
|
-
if (
|
271
|
-
this.logger.warn(`[
|
272
|
+
if (APP_TO_APP_EVENT_TYPES.includes(type)) {
|
273
|
+
this.logger.warn(`[AppSession] Attempted to unsubscribe from App-to-App event type '${type}', which is not a valid stream.`);
|
272
274
|
return;
|
273
275
|
}
|
274
276
|
this.subscriptions.delete(type);
|
@@ -536,7 +538,7 @@ class TpaSession {
|
|
536
538
|
this.pendingPhotoRequests.set(requestId, { resolve, reject });
|
537
539
|
// Create photo request message
|
538
540
|
const message = {
|
539
|
-
type: types_1.
|
541
|
+
type: types_1.AppToCloudMessageType.PHOTO_REQUEST,
|
540
542
|
packageName: this.config.packageName,
|
541
543
|
sessionId: this.sessionId,
|
542
544
|
timestamp: new Date(),
|
@@ -578,7 +580,7 @@ class TpaSession {
|
|
578
580
|
}
|
579
581
|
/**
|
580
582
|
* ⚙️ Configure settings-based subscription updates
|
581
|
-
* This allows
|
583
|
+
* This allows Apps to automatically update their subscriptions when certain settings change
|
582
584
|
* @param options Configuration options for settings-based subscriptions
|
583
585
|
*/
|
584
586
|
setSubscriptionSettings(options) {
|
@@ -634,32 +636,32 @@ class TpaSession {
|
|
634
636
|
}
|
635
637
|
/**
|
636
638
|
* 📝 Load configuration from a JSON file
|
637
|
-
* @param jsonData JSON string containing
|
639
|
+
* @param jsonData JSON string containing App configuration
|
638
640
|
* @returns The loaded configuration
|
639
641
|
* @throws Error if the configuration is invalid
|
640
642
|
*/
|
641
643
|
loadConfigFromJson(jsonData) {
|
642
644
|
try {
|
643
645
|
const parsedConfig = JSON.parse(jsonData);
|
644
|
-
if ((0, types_1.
|
645
|
-
this.
|
646
|
+
if ((0, types_1.validateAppConfig)(parsedConfig)) {
|
647
|
+
this.appConfig = parsedConfig;
|
646
648
|
return parsedConfig;
|
647
649
|
}
|
648
650
|
else {
|
649
|
-
throw new Error('Invalid
|
651
|
+
throw new Error('Invalid App configuration format');
|
650
652
|
}
|
651
653
|
}
|
652
654
|
catch (error) {
|
653
655
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
654
|
-
throw new Error(`Failed to load
|
656
|
+
throw new Error(`Failed to load App configuration: ${errorMessage}`);
|
655
657
|
}
|
656
658
|
}
|
657
659
|
/**
|
658
|
-
* 📋 Get the loaded
|
659
|
-
* @returns The current
|
660
|
+
* 📋 Get the loaded App configuration
|
661
|
+
* @returns The current App configuration or null if not loaded
|
660
662
|
*/
|
661
663
|
getConfig() {
|
662
|
-
return this.
|
664
|
+
return this.appConfig;
|
663
665
|
}
|
664
666
|
/**
|
665
667
|
* 🔌 Get the WebSocket server URL for this session
|
@@ -672,28 +674,28 @@ class TpaSession {
|
|
672
674
|
if (!this.config.augmentOSWebsocketUrl) {
|
673
675
|
return undefined;
|
674
676
|
}
|
675
|
-
return
|
677
|
+
return AppSession.convertToHttps(this.config.augmentOSWebsocketUrl);
|
676
678
|
}
|
677
679
|
static convertToHttps(rawUrl) {
|
678
680
|
if (!rawUrl)
|
679
681
|
return '';
|
680
682
|
// Remove ws:// or wss://
|
681
683
|
let url = rawUrl.replace(/^wss?:\/\//, '');
|
682
|
-
// Remove trailing /
|
683
|
-
url = url.replace(/\/
|
684
|
+
// Remove trailing /app-ws
|
685
|
+
url = url.replace(/\/app-ws$/, '');
|
684
686
|
// Prepend https://
|
685
687
|
return `https://${url}`;
|
686
688
|
}
|
687
689
|
/**
|
688
|
-
* 🔍 Get default settings from the
|
690
|
+
* 🔍 Get default settings from the App configuration
|
689
691
|
* @returns Array of settings with default values
|
690
692
|
* @throws Error if configuration is not loaded
|
691
693
|
*/
|
692
694
|
getDefaultSettings() {
|
693
|
-
if (!this.
|
694
|
-
throw new Error('
|
695
|
+
if (!this.appConfig) {
|
696
|
+
throw new Error('App configuration not loaded. Call loadConfigFromJson first.');
|
695
697
|
}
|
696
|
-
return this.
|
698
|
+
return this.appConfig.settings
|
697
699
|
.filter((s) => s.type !== 'group')
|
698
700
|
.map((s) => ({
|
699
701
|
...s,
|
@@ -706,9 +708,9 @@ class TpaSession {
|
|
706
708
|
* @returns The setting schema or undefined if not found
|
707
709
|
*/
|
708
710
|
getSettingSchema(key) {
|
709
|
-
if (!this.
|
711
|
+
if (!this.appConfig)
|
710
712
|
return undefined;
|
711
|
-
const setting = this.
|
713
|
+
const setting = this.appConfig.settings.find((s) => s.type !== 'group' && 'key' in s && s.key === key);
|
712
714
|
return setting;
|
713
715
|
}
|
714
716
|
// =====================================
|
@@ -731,16 +733,16 @@ class TpaSession {
|
|
731
733
|
}
|
732
734
|
// Using type guards to determine message type and safely handle each case
|
733
735
|
try {
|
734
|
-
if ((0, types_1.
|
736
|
+
if ((0, types_1.isAppConnectionAck)(message)) {
|
735
737
|
// Get settings from connection acknowledgment
|
736
738
|
const receivedSettings = message.settings || [];
|
737
739
|
this.settingsData = receivedSettings;
|
738
740
|
// Store config if provided
|
739
|
-
if (message.config && (0, types_1.
|
740
|
-
this.
|
741
|
+
if (message.config && (0, types_1.validateAppConfig)(message.config)) {
|
742
|
+
this.appConfig = message.config;
|
741
743
|
}
|
742
744
|
// Use default settings from config if no settings were provided
|
743
|
-
if (receivedSettings.length === 0 && this.
|
745
|
+
if (receivedSettings.length === 0 && this.appConfig) {
|
744
746
|
try {
|
745
747
|
this.settingsData = this.getDefaultSettings();
|
746
748
|
}
|
@@ -751,13 +753,21 @@ class TpaSession {
|
|
751
753
|
// Update the settings manager with the new settings
|
752
754
|
this.settings.updateSettings(this.settingsData);
|
753
755
|
// Handle AugmentOS system settings if provided
|
754
|
-
this.logger.debug(`[
|
756
|
+
this.logger.debug(`[AppSession] CONNECTION_ACK augmentosSettings:`, message.augmentosSettings);
|
755
757
|
if (message.augmentosSettings) {
|
756
|
-
this.logger.info(`[
|
758
|
+
this.logger.info(`[AppSession] Calling updateAugmentosSettings with:`, message.augmentosSettings);
|
757
759
|
this.settings.updateAugmentosSettings(message.augmentosSettings);
|
758
760
|
}
|
759
761
|
else {
|
760
|
-
this.logger.warn(`[
|
762
|
+
this.logger.warn(`[AppSession] CONNECTION_ACK message missing augmentosSettings field`);
|
763
|
+
}
|
764
|
+
// Handle device capabilities if provided
|
765
|
+
if (message.capabilities) {
|
766
|
+
this.capabilities = message.capabilities;
|
767
|
+
this.logger.info(`[AppSession] Device capabilities loaded for model: ${message.capabilities.modelName}`);
|
768
|
+
}
|
769
|
+
else {
|
770
|
+
this.logger.debug(`[AppSession] No capabilities provided in CONNECTION_ACK`);
|
761
771
|
}
|
762
772
|
// Emit connected event with settings
|
763
773
|
this.events.emit('connected', this.settingsData);
|
@@ -768,8 +778,8 @@ class TpaSession {
|
|
768
778
|
this.updateSubscriptionsFromSettings();
|
769
779
|
}
|
770
780
|
}
|
771
|
-
else if ((0, types_1.
|
772
|
-
// Handle both
|
781
|
+
else if ((0, types_1.isAppConnectionError)(message) || message.type === 'connection_error') {
|
782
|
+
// Handle both App-specific connection_error and standard connection_error
|
773
783
|
const errorMessage = message.message || 'Unknown connection error';
|
774
784
|
this.events.emit('error', new Error(errorMessage));
|
775
785
|
}
|
@@ -799,7 +809,7 @@ class TpaSession {
|
|
799
809
|
this.events.emit(messageStreamType, sanitizedData);
|
800
810
|
}
|
801
811
|
}
|
802
|
-
else if ((0,
|
812
|
+
else if ((0, cloud_to_app_1.isPhotoResponse)(message)) {
|
803
813
|
// Handle photo response by resolving the pending promise
|
804
814
|
if (this.pendingPhotoRequests.has(message.requestId)) {
|
805
815
|
const { resolve } = this.pendingPhotoRequests.get(message.requestId);
|
@@ -807,7 +817,7 @@ class TpaSession {
|
|
807
817
|
this.pendingPhotoRequests.delete(message.requestId);
|
808
818
|
}
|
809
819
|
}
|
810
|
-
else if ((0,
|
820
|
+
else if ((0, cloud_to_app_1.isRtmpStreamStatus)(message)) {
|
811
821
|
// Emit as a standard stream event if subscribed
|
812
822
|
if (this.subscriptions.has(types_1.StreamType.RTMP_STREAM_STATUS)) {
|
813
823
|
this.events.emit(types_1.StreamType.RTMP_STREAM_STATUS, message);
|
@@ -882,24 +892,24 @@ class TpaSession {
|
|
882
892
|
}
|
883
893
|
}
|
884
894
|
// Handle custom messages
|
885
|
-
else if (message.type === types_1.
|
895
|
+
else if (message.type === types_1.CloudToAppMessageType.CUSTOM_MESSAGE) {
|
886
896
|
this.events.emit('custom_message', message);
|
887
897
|
return;
|
888
898
|
}
|
889
|
-
// Handle
|
890
|
-
else if (message.type === '
|
891
|
-
this.
|
899
|
+
// Handle App-to-App communication messages
|
900
|
+
else if (message.type === 'app_message_received') {
|
901
|
+
this.appEvents.emit('app_message_received', message);
|
892
902
|
}
|
893
|
-
else if (message.type === '
|
894
|
-
this.
|
903
|
+
else if (message.type === 'app_user_joined') {
|
904
|
+
this.appEvents.emit('app_user_joined', message);
|
895
905
|
}
|
896
|
-
else if (message.type === '
|
897
|
-
this.
|
906
|
+
else if (message.type === 'app_user_left') {
|
907
|
+
this.appEvents.emit('app_user_left', message);
|
898
908
|
}
|
899
|
-
else if (message.type === '
|
900
|
-
this.
|
909
|
+
else if (message.type === 'app_room_updated') {
|
910
|
+
this.appEvents.emit('app_room_updated', message);
|
901
911
|
}
|
902
|
-
else if (message.type === '
|
912
|
+
else if (message.type === 'app_direct_message_response') {
|
903
913
|
const response = message;
|
904
914
|
if (response.messageId && this.pendingDirectMessages.has(response.messageId)) {
|
905
915
|
const { resolve } = this.pendingDirectMessages.get(response.messageId);
|
@@ -915,11 +925,11 @@ class TpaSession {
|
|
915
925
|
}
|
916
926
|
// Handle 'connection_error' as a specific case if cloud sends this string literal
|
917
927
|
else if (message.type === 'connection_error') {
|
918
|
-
// Treat 'connection_error' (string literal) like
|
928
|
+
// Treat 'connection_error' (string literal) like AppConnectionError
|
919
929
|
// This handles cases where the cloud might send the type as a direct string
|
920
|
-
// instead of the enum's '
|
930
|
+
// instead of the enum's 'app_connection_error' value.
|
921
931
|
const errorMessage = message.message || 'Unknown connection error (type: connection_error)';
|
922
|
-
this.logger.warn(`Received 'connection_error' type directly. Consider aligning cloud to send '
|
932
|
+
this.logger.warn(`Received 'connection_error' type directly. Consider aligning cloud to send 'app_connection_error'. Message: ${errorMessage}`);
|
923
933
|
this.events.emit('error', new Error(errorMessage));
|
924
934
|
}
|
925
935
|
else if (message.type === 'permission_error') {
|
@@ -964,14 +974,14 @@ class TpaSession {
|
|
964
974
|
}
|
965
975
|
}
|
966
976
|
catch (processingError) {
|
967
|
-
// Catch any errors during message processing to prevent
|
977
|
+
// Catch any errors during message processing to prevent App crashes
|
968
978
|
this.logger.error(processingError, 'Error processing message:');
|
969
979
|
const errorMessage = processingError instanceof Error ? processingError.message : String(processingError);
|
970
980
|
this.events.emit('error', new Error(`Error processing message: ${errorMessage}`));
|
971
981
|
}
|
972
982
|
}
|
973
983
|
catch (error) {
|
974
|
-
// Final safety net to ensure the
|
984
|
+
// Final safety net to ensure the App doesn't crash on any unexpected errors
|
975
985
|
this.logger.error(error, 'Unexpected error in message handler');
|
976
986
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
977
987
|
this.events.emit('error', new Error(`Unexpected error in message handler: ${errorMessage}`));
|
@@ -1083,7 +1093,7 @@ class TpaSession {
|
|
1083
1093
|
*/
|
1084
1094
|
sendConnectionInit() {
|
1085
1095
|
const message = {
|
1086
|
-
type: types_1.
|
1096
|
+
type: types_1.AppToCloudMessageType.CONNECTION_INIT,
|
1087
1097
|
sessionId: this.sessionId,
|
1088
1098
|
packageName: this.config.packageName,
|
1089
1099
|
apiKey: this.config.apiKey,
|
@@ -1095,9 +1105,9 @@ class TpaSession {
|
|
1095
1105
|
* 📝 Update subscription list with cloud
|
1096
1106
|
*/
|
1097
1107
|
updateSubscriptions() {
|
1098
|
-
this.logger.info(`[
|
1108
|
+
this.logger.info(`[AppSession] updateSubscriptions: sending subscriptions to cloud:`, Array.from(this.subscriptions));
|
1099
1109
|
const message = {
|
1100
|
-
type: types_1.
|
1110
|
+
type: types_1.AppToCloudMessageType.SUBSCRIPTION_UPDATE,
|
1101
1111
|
packageName: this.config.packageName,
|
1102
1112
|
subscriptions: Array.from(this.subscriptions),
|
1103
1113
|
sessionId: this.sessionId,
|
@@ -1118,7 +1128,7 @@ class TpaSession {
|
|
1118
1128
|
const maxAttempts = this.config.maxReconnectAttempts || 3;
|
1119
1129
|
if (this.reconnectAttempts >= maxAttempts) {
|
1120
1130
|
this.logger.info(`🔄 Maximum reconnection attempts (${maxAttempts}) reached, giving up`);
|
1121
|
-
// Emit a permanent disconnection event to trigger onStop in the
|
1131
|
+
// Emit a permanent disconnection event to trigger onStop in the App server
|
1122
1132
|
this.events.emit('disconnected', {
|
1123
1133
|
message: `Connection permanently lost after ${maxAttempts} failed reconnection attempts`,
|
1124
1134
|
code: 4000, // Custom code for max reconnection attempts exhausted
|
@@ -1203,7 +1213,7 @@ class TpaSession {
|
|
1203
1213
|
}
|
1204
1214
|
}
|
1205
1215
|
catch (error) {
|
1206
|
-
// Log the error and emit an event so
|
1216
|
+
// Log the error and emit an event so App developers are aware
|
1207
1217
|
this.logger.error(error, 'Message send error');
|
1208
1218
|
// Ensure we always emit an Error object
|
1209
1219
|
if (error instanceof Error) {
|
@@ -1232,22 +1242,22 @@ class TpaSession {
|
|
1232
1242
|
}
|
1233
1243
|
}
|
1234
1244
|
// =====================================
|
1235
|
-
// 👥
|
1245
|
+
// 👥 App-to-App Communication Interface
|
1236
1246
|
// =====================================
|
1237
1247
|
/**
|
1238
|
-
* 👥 Discover other users currently using the same
|
1248
|
+
* 👥 Discover other users currently using the same App
|
1239
1249
|
* @param includeProfiles - Whether to include user profile information
|
1240
1250
|
* @returns Promise that resolves with list of active users
|
1241
1251
|
*/
|
1242
|
-
async
|
1252
|
+
async discoverAppUsers(domain, includeProfiles = false) {
|
1243
1253
|
// Use the domain argument as the base URL if provided
|
1244
1254
|
if (!domain) {
|
1245
1255
|
throw new Error('Domain (API base URL) is required for user discovery');
|
1246
1256
|
}
|
1247
|
-
const url = `${domain}/api/
|
1257
|
+
const url = `${domain}/api/app-communication/discover-users`;
|
1248
1258
|
// Use the user's core token for authentication
|
1249
|
-
const
|
1250
|
-
if (!
|
1259
|
+
const appApiKey = this.config.apiKey; // This may need to be updated if you store the core token elsewhere
|
1260
|
+
if (!appApiKey) {
|
1251
1261
|
throw new Error('Core token (apiKey) is required for user discovery');
|
1252
1262
|
}
|
1253
1263
|
const body = {
|
@@ -1258,7 +1268,7 @@ class TpaSession {
|
|
1258
1268
|
const response = await fetch(url, {
|
1259
1269
|
method: 'POST',
|
1260
1270
|
headers: {
|
1261
|
-
'Authorization': `Bearer ${
|
1271
|
+
'Authorization': `Bearer ${appApiKey}`,
|
1262
1272
|
'Content-Type': 'application/json'
|
1263
1273
|
},
|
1264
1274
|
body: JSON.stringify(body)
|
@@ -1276,7 +1286,7 @@ class TpaSession {
|
|
1276
1286
|
*/
|
1277
1287
|
async isUserActive(userId) {
|
1278
1288
|
try {
|
1279
|
-
const userList = await this.
|
1289
|
+
const userList = await this.discoverAppUsers('', false);
|
1280
1290
|
return userList.users.some((user) => user.userId === userId);
|
1281
1291
|
}
|
1282
1292
|
catch (error) {
|
@@ -1285,12 +1295,12 @@ class TpaSession {
|
|
1285
1295
|
}
|
1286
1296
|
}
|
1287
1297
|
/**
|
1288
|
-
* 📊 Get user count for this
|
1298
|
+
* 📊 Get user count for this App
|
1289
1299
|
* @returns Promise that resolves with number of active users
|
1290
1300
|
*/
|
1291
1301
|
async getUserCount(domain) {
|
1292
1302
|
try {
|
1293
|
-
const userList = await this.
|
1303
|
+
const userList = await this.discoverAppUsers(domain, false);
|
1294
1304
|
return userList.totalUsers;
|
1295
1305
|
}
|
1296
1306
|
catch (error) {
|
@@ -1299,16 +1309,16 @@ class TpaSession {
|
|
1299
1309
|
}
|
1300
1310
|
}
|
1301
1311
|
/**
|
1302
|
-
* 📢 Send broadcast message to all users with same
|
1312
|
+
* 📢 Send broadcast message to all users with same App active
|
1303
1313
|
* @param payload - Message payload to send
|
1304
1314
|
* @param roomId - Optional room ID for room-based messaging
|
1305
1315
|
* @returns Promise that resolves when message is sent
|
1306
1316
|
*/
|
1307
|
-
async
|
1317
|
+
async broadcastToAppUsers(payload, roomId) {
|
1308
1318
|
try {
|
1309
1319
|
const messageId = this.generateMessageId();
|
1310
1320
|
const message = {
|
1311
|
-
type: '
|
1321
|
+
type: 'app_broadcast_message',
|
1312
1322
|
packageName: this.config.packageName,
|
1313
1323
|
sessionId: this.sessionId,
|
1314
1324
|
payload,
|
@@ -1336,7 +1346,7 @@ class TpaSession {
|
|
1336
1346
|
// Store promise resolver
|
1337
1347
|
this.pendingDirectMessages.set(messageId, { resolve, reject });
|
1338
1348
|
const message = {
|
1339
|
-
type: '
|
1349
|
+
type: 'app_direct_message',
|
1340
1350
|
packageName: this.config.packageName,
|
1341
1351
|
sessionId: this.sessionId,
|
1342
1352
|
targetUserId,
|
@@ -1367,10 +1377,10 @@ class TpaSession {
|
|
1367
1377
|
* @param roomConfig - Optional room configuration
|
1368
1378
|
* @returns Promise that resolves when room is joined
|
1369
1379
|
*/
|
1370
|
-
async
|
1380
|
+
async joinAppRoom(roomId, roomConfig) {
|
1371
1381
|
try {
|
1372
1382
|
const message = {
|
1373
|
-
type: '
|
1383
|
+
type: 'app_room_join',
|
1374
1384
|
packageName: this.config.packageName,
|
1375
1385
|
sessionId: this.sessionId,
|
1376
1386
|
roomId,
|
@@ -1389,10 +1399,10 @@ class TpaSession {
|
|
1389
1399
|
* @param roomId - Room ID to leave
|
1390
1400
|
* @returns Promise that resolves when room is left
|
1391
1401
|
*/
|
1392
|
-
async
|
1402
|
+
async leaveAppRoom(roomId) {
|
1393
1403
|
try {
|
1394
1404
|
const message = {
|
1395
|
-
type: '
|
1405
|
+
type: 'app_room_leave',
|
1396
1406
|
packageName: this.config.packageName,
|
1397
1407
|
sessionId: this.sessionId,
|
1398
1408
|
roomId,
|
@@ -1406,40 +1416,40 @@ class TpaSession {
|
|
1406
1416
|
}
|
1407
1417
|
}
|
1408
1418
|
/**
|
1409
|
-
* 📨 Listen for messages from other
|
1419
|
+
* 📨 Listen for messages from other App users
|
1410
1420
|
* @param handler - Function to handle incoming messages
|
1411
1421
|
* @returns Cleanup function to remove the handler
|
1412
1422
|
*/
|
1413
|
-
|
1414
|
-
this.
|
1415
|
-
return () => this.
|
1423
|
+
onAppMessage(handler) {
|
1424
|
+
this.appEvents.on('app_message_received', handler);
|
1425
|
+
return () => this.appEvents.off('app_message_received', handler);
|
1416
1426
|
}
|
1417
1427
|
/**
|
1418
1428
|
* 👋 Listen for user join events
|
1419
1429
|
* @param handler - Function to handle user join events
|
1420
1430
|
* @returns Cleanup function to remove the handler
|
1421
1431
|
*/
|
1422
|
-
|
1423
|
-
this.
|
1424
|
-
return () => this.
|
1432
|
+
onAppUserJoined(handler) {
|
1433
|
+
this.appEvents.on('app_user_joined', handler);
|
1434
|
+
return () => this.appEvents.off('app_user_joined', handler);
|
1425
1435
|
}
|
1426
1436
|
/**
|
1427
1437
|
* 🚪 Listen for user leave events
|
1428
1438
|
* @param handler - Function to handle user leave events
|
1429
1439
|
* @returns Cleanup function to remove the handler
|
1430
1440
|
*/
|
1431
|
-
|
1432
|
-
this.
|
1433
|
-
return () => this.
|
1441
|
+
onAppUserLeft(handler) {
|
1442
|
+
this.appEvents.on('app_user_left', handler);
|
1443
|
+
return () => this.appEvents.off('app_user_left', handler);
|
1434
1444
|
}
|
1435
1445
|
/**
|
1436
1446
|
* 🏠 Listen for room update events
|
1437
1447
|
* @param handler - Function to handle room updates
|
1438
1448
|
* @returns Cleanup function to remove the handler
|
1439
1449
|
*/
|
1440
|
-
|
1441
|
-
this.
|
1442
|
-
return () => this.
|
1450
|
+
onAppRoomUpdated(handler) {
|
1451
|
+
this.appEvents.on('app_room_updated', handler);
|
1452
|
+
return () => this.appEvents.off('app_room_updated', handler);
|
1443
1453
|
}
|
1444
1454
|
/**
|
1445
1455
|
* 🔧 Generate unique message ID
|
@@ -1449,4 +1459,4 @@ class TpaSession {
|
|
1449
1459
|
return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 9)}`;
|
1450
1460
|
}
|
1451
1461
|
}
|
1452
|
-
exports.
|
1462
|
+
exports.AppSession = AppSession;
|
@@ -1,7 +1,7 @@
|
|
1
1
|
/**
|
2
2
|
* 🎨 Layout Manager Module
|
3
3
|
*
|
4
|
-
* Manages AR display layouts for
|
4
|
+
* Manages AR display layouts for Apps. This class provides an easy-to-use interface
|
5
5
|
* for showing different types of content in the user's AR view.
|
6
6
|
*
|
7
7
|
* @example
|
@@ -22,7 +22,7 @@ export declare class LayoutManager {
|
|
22
22
|
/**
|
23
23
|
* 🎯 Creates a new LayoutManager instance
|
24
24
|
*
|
25
|
-
* @param packageName -
|
25
|
+
* @param packageName - App package identifier
|
26
26
|
* @param sendMessage - Function to send display requests to AugmentOS
|
27
27
|
*/
|
28
28
|
constructor(packageName: string, sendMessage: (message: DisplayRequest) => void);
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"layouts.d.ts","sourceRoot":"","sources":["../../../src/
|
1
|
+
{"version":3,"file":"layouts.d.ts","sourceRoot":"","sources":["../../../src/app/session/layouts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EACL,cAAc,EAOd,QAAQ,EAGT,MAAM,aAAa,CAAC;AAErB,qBAAa,aAAa;IAQtB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,WAAW;IARrB;;;;;OAKG;gBAEO,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI;IAGxD;;;;;;;;OAQG;IACH,OAAO,CAAC,kBAAkB;IAmG1B;;;;;;;;;;;;;;;;;OAiBG;IACH,YAAY,CACV,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAC;IAuCnD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,kBAAkB,CAChB,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;IAcpD;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,iBAAiB,CACf,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;IAclD;;;;;;;;;;;;KAYC;IACH,cAAc,CACZ,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;IAapD;;;;;;;;;;;;;;;;OAgBG;IACH,iBAAiB,CACf,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,EACjB,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;CAarD"}
|