@ikonai/sdk 0.0.1

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.
@@ -0,0 +1,130 @@
1
+ import { EndpointSelector } from '../client/endpoint-selector';
2
+ import { Entrypoint, EntrypointType, ProtocolMessage } from '../../../platform-generated/src/index.ts';
3
+ /**
4
+ * ChannelManager state.
5
+ */
6
+ export type ChannelManagerState = 'idle' | 'connecting' | 'connected' | 'reconnecting' | 'stopped' | 'offline';
7
+ /**
8
+ * Configuration for ChannelManager.
9
+ */
10
+ export interface ChannelManagerConfig {
11
+ /**
12
+ * Session ID from auth response.
13
+ */
14
+ sessionId: number;
15
+ /**
16
+ * Keepalive timeout in milliseconds.
17
+ */
18
+ keepaliveTimeoutMs: number;
19
+ /**
20
+ * Reconnect backoff in milliseconds.
21
+ */
22
+ reconnectBackoffMs: number;
23
+ /**
24
+ * Maximum reconnection attempts.
25
+ */
26
+ maxReconnectAttempts: number;
27
+ /**
28
+ * Endpoint selector for ordering types.
29
+ */
30
+ endpointSelector: EndpointSelector;
31
+ /**
32
+ * Callback when a protocol message is received from any channel.
33
+ */
34
+ onProtocolMessage?: (message: ProtocolMessage) => void;
35
+ /**
36
+ * Callback when state changes.
37
+ */
38
+ onStateChange?: (state: ChannelManagerState) => void;
39
+ /**
40
+ * Callback when an error occurs.
41
+ */
42
+ onError?: (error: Error) => void;
43
+ }
44
+ /**
45
+ * ChannelManager orchestrates multiple channels to an Ikon server.
46
+ *
47
+ * Features:
48
+ * - Groups entrypoints by type
49
+ * - Tries types in order (WT → WS → WTProxy → WSProxy for prod)
50
+ * - Connects core channel first, then others in parallel
51
+ * - Handles reconnection with type fallback
52
+ * - Routes messages to/from appropriate channels
53
+ */
54
+ export declare class ChannelManager {
55
+ private channels;
56
+ private activeType;
57
+ private state;
58
+ private reconnectAttempts;
59
+ private shouldReconnect;
60
+ private entrypoints;
61
+ private abortController;
62
+ private readonly config;
63
+ constructor(config: ChannelManagerConfig);
64
+ /**
65
+ * Get the current state.
66
+ */
67
+ get managerState(): ChannelManagerState;
68
+ /**
69
+ * Get the active endpoint type.
70
+ */
71
+ get activeEndpointType(): EntrypointType | null;
72
+ /**
73
+ * Connect to the server using the provided entrypoints.
74
+ */
75
+ connect(entrypoints: Entrypoint[]): Promise<void>;
76
+ /**
77
+ * Disconnect all channels.
78
+ */
79
+ disconnect(): void;
80
+ /**
81
+ * Send a protocol message to the appropriate channel.
82
+ * The opcode group is extracted from the message automatically.
83
+ */
84
+ sendProtocolMessage(message: ProtocolMessage): void;
85
+ /**
86
+ * Send a protocol message to all channels (for broadcast messages).
87
+ */
88
+ sendToAll(message: ProtocolMessage): void;
89
+ /**
90
+ * Internal connect implementation.
91
+ */
92
+ private connectInternal;
93
+ /**
94
+ * Connect all channels for a given endpoint type.
95
+ * Core channel connects first, then others in parallel.
96
+ */
97
+ private connectAllChannels;
98
+ /**
99
+ * Connect a single channel.
100
+ */
101
+ private connectChannel;
102
+ /**
103
+ * Group entrypoints by type.
104
+ */
105
+ private groupByType;
106
+ /**
107
+ * Handle channel state change.
108
+ */
109
+ private handleChannelStateChange;
110
+ /**
111
+ * Handle channel close.
112
+ */
113
+ private handleChannelClose;
114
+ /**
115
+ * Attempt to reconnect with exponential backoff.
116
+ */
117
+ private attemptReconnect;
118
+ /**
119
+ * Disconnect all channels.
120
+ */
121
+ private disconnectAll;
122
+ /**
123
+ * Update and notify state change.
124
+ */
125
+ private setState;
126
+ /**
127
+ * Delay with abort support.
128
+ */
129
+ private delay;
130
+ }
@@ -0,0 +1,102 @@
1
+ import { Entrypoint, EntrypointType, ProtocolMessage } from '../../../platform-generated/src/index.ts';
2
+ /**
3
+ * Channel state.
4
+ */
5
+ export type ChannelState = 'disconnected' | 'connecting' | 'connected' | 'stopped';
6
+ /**
7
+ * Configuration for a single channel.
8
+ */
9
+ export interface ChannelConfig {
10
+ /**
11
+ * The entrypoint to connect to.
12
+ */
13
+ entrypoint: Entrypoint;
14
+ /**
15
+ * Session ID for the channel (from auth response).
16
+ */
17
+ sessionId: number;
18
+ /**
19
+ * Keepalive timeout in milliseconds.
20
+ */
21
+ keepaliveTimeoutMs: number;
22
+ /**
23
+ * Callback when a protocol message is received.
24
+ */
25
+ onProtocolMessage?: (message: ProtocolMessage) => void;
26
+ /**
27
+ * Callback when channel state changes.
28
+ */
29
+ onStateChange?: (state: ChannelState) => void;
30
+ /**
31
+ * Callback when channel is closed.
32
+ */
33
+ onClose?: (reason?: string, wasClean?: boolean) => void;
34
+ /**
35
+ * Callback when an error occurs.
36
+ */
37
+ onError?: (error: Error) => void;
38
+ }
39
+ /**
40
+ * Channel manages a single transport connection to an Ikon server entrypoint.
41
+ *
42
+ * Features:
43
+ * - Connects to a specific entrypoint
44
+ * - Handles message routing
45
+ * - Detects server stopping
46
+ * - No reconnection logic (handled by ChannelManager)
47
+ */
48
+ export declare class Channel {
49
+ private state;
50
+ private transport;
51
+ private readonly config;
52
+ private readonly entrypoint;
53
+ constructor(config: ChannelConfig);
54
+ /**
55
+ * Get the current channel state.
56
+ */
57
+ get channelState(): ChannelState;
58
+ /**
59
+ * Get the opcode groups this channel handles.
60
+ */
61
+ get opcodeGroups(): number;
62
+ /**
63
+ * Get the entrypoint type.
64
+ */
65
+ get type(): EntrypointType;
66
+ /**
67
+ * Check if transport is connected.
68
+ */
69
+ get isConnected(): boolean;
70
+ /**
71
+ * Connect to the entrypoint.
72
+ */
73
+ connect(): Promise<void>;
74
+ /**
75
+ * Disconnect the channel.
76
+ */
77
+ disconnect(): void;
78
+ /**
79
+ * Send a protocol message through the channel.
80
+ */
81
+ send(message: ProtocolMessage): void;
82
+ /**
83
+ * Connect the transport to the entrypoint.
84
+ */
85
+ private connectTransport;
86
+ /**
87
+ * Handle incoming protocol message.
88
+ */
89
+ private handleProtocolMessage;
90
+ /**
91
+ * Handle transport close.
92
+ */
93
+ private handleClose;
94
+ /**
95
+ * Handle transport error.
96
+ */
97
+ private handleError;
98
+ /**
99
+ * Update and notify state change.
100
+ */
101
+ private setState;
102
+ }
@@ -0,0 +1,2 @@
1
+ export { Channel, type ChannelConfig, type ChannelState } from './channel';
2
+ export { ChannelManager, type ChannelManagerConfig, type ChannelManagerState } from './channel-manager';
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Connection state managed by IkonClient.
3
+ * The SDK internally manages UI-related states with timers.
4
+ */
5
+ export type ConnectionState = 'idle' | 'connecting' | 'connectingSlow' | 'connected' | 'reconnecting' | 'offline' | 'offlineError';
6
+ /**
7
+ * Check if the state indicates the client is actively trying to connect.
8
+ */
9
+ export declare function isConnecting(state: ConnectionState): boolean;
10
+ /**
11
+ * Check if the state indicates the client is connected.
12
+ */
13
+ export declare function isConnected(state: ConnectionState): boolean;
14
+ /**
15
+ * Check if the state indicates the client is offline (either normal or error).
16
+ */
17
+ export declare function isOffline(state: ConnectionState): boolean;
18
+ /**
19
+ * Check if the state indicates an error condition.
20
+ */
21
+ export declare function isError(state: ConnectionState): boolean;
@@ -0,0 +1,34 @@
1
+ import { Entrypoint, EntrypointType } from '../../../platform-generated/src/index.ts';
2
+ import { LocalConfig } from './ikon-client-config';
3
+ /**
4
+ * EndpointSelector handles ordering and selection of endpoint types.
5
+ *
6
+ * Behavior varies by environment:
7
+ * - Local: Use endpoints as-is from server (no ordering)
8
+ * - Cloud (browser/apiKey): Order by preference (WT → WS → WTProxy → WSProxy), remember working type
9
+ */
10
+ export declare class EndpointSelector {
11
+ private readonly isLocal;
12
+ private workingEndpointType;
13
+ constructor(config: {
14
+ local?: LocalConfig;
15
+ });
16
+ /**
17
+ * Get ordered list of endpoint types to try.
18
+ * Returns only types that exist in the provided map.
19
+ */
20
+ getOrderedTypes(byType: Map<EntrypointType, Entrypoint[]>): EntrypointType[];
21
+ /**
22
+ * Remember the working endpoint type for future connections.
23
+ * Only stores in cloud mode.
24
+ */
25
+ rememberWorkingType(type: EntrypointType): void;
26
+ /**
27
+ * Clear the remembered endpoint type.
28
+ */
29
+ clearRememberedType(): void;
30
+ /**
31
+ * Load remembered type from localStorage.
32
+ */
33
+ private loadRememberedType;
34
+ }
@@ -0,0 +1,226 @@
1
+ import { ProtocolMessage } from '../../../platform-generated/src/index.ts';
2
+ import { ConnectionState } from './connection-state';
3
+ /**
4
+ * Backend environment type.
5
+ */
6
+ export type BackendType = 'production' | 'development';
7
+ /**
8
+ * Common connection options shared across all modes.
9
+ */
10
+ export interface CommonConnectionConfig {
11
+ /**
12
+ * Device ID for the connection.
13
+ * If not provided, a random one will be generated.
14
+ */
15
+ deviceId?: string;
16
+ /**
17
+ * Product identifier.
18
+ */
19
+ productId?: string;
20
+ /**
21
+ * Version identifier.
22
+ */
23
+ versionId?: string;
24
+ /**
25
+ * User locale (e.g., 'en-US').
26
+ * Defaults to navigator.language or 'en-US'.
27
+ */
28
+ locale?: string;
29
+ /**
30
+ * Description for this client.
31
+ * Default: 'Ikon SDK TypeScript'
32
+ */
33
+ description?: string;
34
+ /**
35
+ * Launch parameters passed to the server.
36
+ */
37
+ parameters?: Record<string, string>;
38
+ /**
39
+ * Opcode groups to receive from server.
40
+ * Default: GROUP_CORE | GROUP_KEEPALIVE | GROUP_EVENTS | GROUP_ACTIONS | GROUP_UI | GROUP_AUDIO | GROUP_VIDEO
41
+ */
42
+ opcodeGroupsFromServer?: number;
43
+ /**
44
+ * Opcode groups to send to server.
45
+ * Default: GROUP_CORE | GROUP_KEEPALIVE | GROUP_EVENTS | GROUP_ACTIONS | GROUP_AUDIO | GROUP_VIDEO
46
+ */
47
+ opcodeGroupsToServer?: number;
48
+ /**
49
+ * Installation ID.
50
+ */
51
+ installId?: string;
52
+ }
53
+ /**
54
+ * Configuration for local development mode.
55
+ */
56
+ export interface LocalConfig extends CommonConnectionConfig {
57
+ /**
58
+ * Host of the local Ikon server.
59
+ * Example: 'localhost'
60
+ */
61
+ host: string;
62
+ /**
63
+ * HTTPS port of the local Ikon server.
64
+ * Example: 8443
65
+ */
66
+ httpsPort: number;
67
+ /**
68
+ * User ID for the connection.
69
+ */
70
+ userId?: string;
71
+ }
72
+ /**
73
+ * Common options for cloud-based modes (browser and apiKey).
74
+ */
75
+ export interface CloudConnectionConfig extends CommonConnectionConfig {
76
+ /**
77
+ * Optional channel key (slug) for spaces with multiple channels.
78
+ * If not provided, connects to the first available channel.
79
+ * Example: 'lobby' or 'main'
80
+ */
81
+ channelKey?: string;
82
+ /**
83
+ * Optional session hash for targeting precomputed sessions.
84
+ */
85
+ hash?: string;
86
+ /**
87
+ * Timeout for provisioning in milliseconds.
88
+ * Default: 60000 (60 seconds)
89
+ */
90
+ provisioningTimeoutMs?: number;
91
+ }
92
+ /**
93
+ * Configuration for browser authentication mode.
94
+ * Use this when the app is hosted on Ikon's domain and user is logged in via browser.
95
+ * Space is auto-discovered from the hostname subdomain.
96
+ * User identity comes from the browser session cookie.
97
+ */
98
+ export interface BrowserConfig extends CloudConnectionConfig {
99
+ }
100
+ /**
101
+ * Configuration for API key authentication mode.
102
+ * Use this for programmatic/library access to cloud channels.
103
+ */
104
+ export interface ApiKeyConfig extends CloudConnectionConfig {
105
+ /**
106
+ * API key for the space (from portal, format: 'ikon-xxxxx').
107
+ */
108
+ apiKey: string;
109
+ /**
110
+ * Space ID (MongoDB ObjectId from portal).
111
+ */
112
+ spaceId: string;
113
+ /**
114
+ * External user identifier - an arbitrary string to identify the user.
115
+ * This does not need to be an internal Ikon user ID.
116
+ * The backend will create/map an internal user for this external ID.
117
+ */
118
+ externalUserId: string;
119
+ /**
120
+ * Backend environment. Defaults to 'production'.
121
+ * - 'production' → https://api.prod.ikon.live
122
+ * - 'development' → https://api.dev.ikon.live
123
+ */
124
+ backendType?: BackendType;
125
+ /**
126
+ * User type for this connection.
127
+ * Use UserType enum values (e.g., UserType.Human, UserType.Agent).
128
+ * Default: UserType.Human
129
+ */
130
+ userType?: number;
131
+ /**
132
+ * Client type for this connection.
133
+ * Use ClientType enum values (e.g., ClientType.DesktopWeb, ClientType.Plugin).
134
+ * Default: ClientType.DesktopWeb
135
+ */
136
+ clientType?: number;
137
+ }
138
+ /**
139
+ * Timeout configuration for the SDK.
140
+ */
141
+ export interface TimeoutConfig {
142
+ /**
143
+ * Duration in milliseconds before transitioning from 'connecting' to 'connectingSlow'.
144
+ * Default: 5000 (5 seconds)
145
+ */
146
+ slowConnectionThresholdMs?: number;
147
+ /**
148
+ * Duration in milliseconds before giving up and showing offline.
149
+ * Default: 30000 (30 seconds)
150
+ */
151
+ connectionTimeoutMs?: number;
152
+ /**
153
+ * Keepalive timeout in milliseconds.
154
+ * If no keepalive is received within this time, the connection is considered dead.
155
+ * Default: 125000 (125 seconds)
156
+ */
157
+ keepaliveTimeoutMs?: number;
158
+ /**
159
+ * Initial backoff for reconnection in milliseconds.
160
+ * Default: 1000 (1 second)
161
+ */
162
+ reconnectBackoffMs?: number;
163
+ /**
164
+ * Maximum number of reconnection attempts.
165
+ * Default: 5
166
+ */
167
+ maxReconnectAttempts?: number;
168
+ }
169
+ /**
170
+ * Configuration for IkonClient.
171
+ */
172
+ export interface IkonClientConfig {
173
+ /**
174
+ * Local server configuration for development mode.
175
+ * Use this when connecting to a local Ikon server.
176
+ */
177
+ local?: LocalConfig;
178
+ /**
179
+ * Browser-based authentication.
180
+ * Use this when the app is hosted on Ikon's domain and user is logged in via browser.
181
+ * Space is auto-discovered from hostname subdomain.
182
+ */
183
+ browser?: BrowserConfig;
184
+ /**
185
+ * API key authentication for programmatic access.
186
+ * Use this for libraries, scripts, plugins that need to connect to cloud channels.
187
+ */
188
+ apiKey?: ApiKeyConfig;
189
+ /**
190
+ * Timeout configuration.
191
+ */
192
+ timeouts?: TimeoutConfig;
193
+ /**
194
+ * Callback when a protocol message is received.
195
+ * The SDK handles keepalive internally; other messages are passed to this callback.
196
+ * Use getOpcode(message) or readProtocolMessageHeaders(message) to extract details.
197
+ */
198
+ onProtocolMessage?: (message: ProtocolMessage) => void;
199
+ /**
200
+ * Callback when connection state changes.
201
+ */
202
+ onConnectionStateChange?: (state: ConnectionState) => void;
203
+ /**
204
+ * Callback when an error occurs.
205
+ */
206
+ onError?: (error: Error) => void;
207
+ /**
208
+ * Callback when tab visibility changes (browser only).
209
+ * Called when the tab is backgrounded or foregrounded.
210
+ * @param isVisible true when tab becomes visible, false when hidden
211
+ */
212
+ onVisibilityChange?: (isVisible: boolean) => void;
213
+ /**
214
+ * Called when connected to the server (including reconnects).
215
+ * Perform any initialization here. After this callback completes,
216
+ * the SDK sends ClientReady to the server.
217
+ * Can be async (return a Promise).
218
+ */
219
+ onReady?: () => void | Promise<void>;
220
+ }
221
+ export declare const DEFAULT_SLOW_CONNECTION_THRESHOLD_MS = 5000;
222
+ export declare const DEFAULT_CONNECTION_TIMEOUT_MS = 30000;
223
+ export declare const DEFAULT_KEEPALIVE_TIMEOUT_MS = 125000;
224
+ export declare const DEFAULT_RECONNECT_BACKOFF_MS = 500;
225
+ export declare const DEFAULT_MAX_RECONNECT_ATTEMPTS = 6;
226
+ export declare const DEFAULT_PROVISIONING_TIMEOUT_MS = 60000;
@@ -0,0 +1,155 @@
1
+ import { ProtocolMessage } from '../../../platform-generated/src/index.ts';
2
+ import { ConnectionState } from './connection-state';
3
+ import { IkonClientConfig } from './ikon-client-config';
4
+ /**
5
+ * Protocol message handler callback type for subscribers.
6
+ */
7
+ export type ProtocolMessageHandler = (message: ProtocolMessage) => void;
8
+ /**
9
+ * State handler callback type for state subscribers.
10
+ */
11
+ export type StateHandler = (state: ConnectionState) => void;
12
+ /**
13
+ * IkonClient is the main entry point for connecting to an Ikon server.
14
+ *
15
+ * Features:
16
+ * - Manages connection lifecycle
17
+ * - Provides UI-friendly connection states (idle, connecting, connectingSlow, connected, offline, offlineError)
18
+ * - Handles timeouts for connection establishment
19
+ * - Passes protocol messages to application via callback
20
+ * - Multi-channel support (core, audio, video on separate connections)
21
+ * - Smart endpoint selection (WT → WS → WTProxy → WSProxy)
22
+ *
23
+ * Usage:
24
+ * ```typescript
25
+ * const client = new IkonClient({
26
+ * local: { host: 'localhost', httpsPort: 8443 },
27
+ * onProtocolMessage: (message) => {
28
+ * const opcode = getOpcode(message)
29
+ * // Handle protocol messages
30
+ * },
31
+ * onConnectionStateChange: (state) => {
32
+ * // Update UI based on state
33
+ * }
34
+ * })
35
+ *
36
+ * await client.connect()
37
+ * ```
38
+ */
39
+ export declare class IkonClient {
40
+ private channelManager;
41
+ private authResponse;
42
+ private currentState;
43
+ private slowConnectionTimer;
44
+ private connectionTimer;
45
+ private messageSubscribers;
46
+ private stateSubscribers;
47
+ private abortController;
48
+ private readonly config;
49
+ private readonly slowConnectionThresholdMs;
50
+ private readonly connectionTimeoutMs;
51
+ private readonly endpointSelector;
52
+ private boundBeforeUnload;
53
+ private boundPageHide;
54
+ private boundVisibilityChange;
55
+ constructor(config: IkonClientConfig);
56
+ private _lastError;
57
+ /**
58
+ * Get the error that caused 'offlineError' state, if any.
59
+ * Returns undefined if not in error state.
60
+ */
61
+ get lastError(): Error | undefined;
62
+ private _sessionId;
63
+ /**
64
+ * Get the session ID from the server.
65
+ * Returns undefined if not connected.
66
+ */
67
+ get sessionId(): number | undefined;
68
+ /**
69
+ * Get the current connection state.
70
+ */
71
+ get connectionState(): ConnectionState;
72
+ /**
73
+ * Connect to the Ikon server.
74
+ * Returns when connected or throws if connection fails.
75
+ */
76
+ connect(): Promise<void>;
77
+ /**
78
+ * Disconnect from the server.
79
+ */
80
+ disconnect(): void;
81
+ /**
82
+ * Send a protocol message to the server.
83
+ * Routes to appropriate channel based on the message's opcode group.
84
+ */
85
+ sendProtocolMessage(message: ProtocolMessage): void;
86
+ /**
87
+ * Subscribe to protocol messages.
88
+ * Returns an unsubscribe function.
89
+ */
90
+ subscribeToProtocolMessages(handler: ProtocolMessageHandler): () => void;
91
+ /**
92
+ * Subscribe to connection state changes.
93
+ * Handler is called immediately with current state, then on every change.
94
+ * Returns an unsubscribe function.
95
+ */
96
+ subscribeToState(handler: StateHandler): () => void;
97
+ /**
98
+ * Authenticate with the server.
99
+ */
100
+ private authenticate;
101
+ /**
102
+ * Handle incoming protocol message from channel manager.
103
+ */
104
+ private handleProtocolMessage;
105
+ /**
106
+ * Handle channel manager state changes.
107
+ */
108
+ private handleChannelManagerStateChange;
109
+ /**
110
+ * Update the connection state and notify subscribers.
111
+ */
112
+ private setState;
113
+ /**
114
+ * Set the offlineError state with an associated error.
115
+ * Use this for unrecoverable SDK internal errors.
116
+ */
117
+ private setErrorState;
118
+ /**
119
+ * Clear all timers.
120
+ */
121
+ private clearTimers;
122
+ /**
123
+ * Set up browser lifecycle event handlers.
124
+ */
125
+ private setupLifecycleHandlers;
126
+ /**
127
+ * Clean up browser lifecycle event handlers.
128
+ */
129
+ private cleanupLifecycleHandlers;
130
+ /**
131
+ * Handle page beforeunload event.
132
+ * Close connection cleanly to avoid orphaned connections on the server.
133
+ */
134
+ private handleBeforeUnload;
135
+ /**
136
+ * Handle page hide event (mobile-friendly, bfcache compatible).
137
+ * Only disconnect if page is actually being unloaded (not persisted).
138
+ */
139
+ private handlePageHide;
140
+ /**
141
+ * Handle visibility change event.
142
+ * Check connection health when tab becomes visible again.
143
+ */
144
+ private handleVisibilityChange;
145
+ /**
146
+ * Check if the connection is still healthy after tab was backgrounded.
147
+ * If connection died while backgrounded, trigger reconnection.
148
+ */
149
+ private checkConnectionHealth;
150
+ /**
151
+ * Handle connection ready - call user's onReady callback, then send ClientReady.
152
+ * Called on every connect (including reconnects).
153
+ */
154
+ private handleReady;
155
+ }