@ikonai/sdk 1.5.0 → 1.6.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/assets/protocol-worker-CW7oSQmQ.js +3 -0
- package/channel/channel-manager.d.ts +12 -0
- package/channel/channel.d.ts +16 -0
- package/client/endpoint-selector.d.ts +27 -0
- package/client/ikon-client-config.d.ts +13 -2
- package/client/ikon-client.d.ts +82 -1
- package/connection/urls.d.ts +13 -9
- package/errors/index.d.ts +27 -0
- package/{ikon-media-DFsofNyM.js → ikon-media-CdIF9gbL.js} +1 -1
- package/index.d.ts +5 -4
- package/index.js +1470 -1023
- package/package.json +1 -1
- package/transport/http-stream-transport.d.ts +107 -0
- package/transport/message-framer.d.ts +36 -0
- package/transport/transport.d.ts +20 -0
- package/transport/web-transport-transport.d.ts +1 -20
- package/utils/embedded-oauth.d.ts +0 -9
- package/utils/log-sender.d.ts +1 -0
- package/utils/query-params.d.ts +85 -49
- package/assets/protocol-worker-CrtCRqQw.js +0 -1
package/package.json
CHANGED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { ProtocolMessage } from '../../shared/protocol/src/index.ts';
|
|
2
|
+
import { HttpStreamMode, Transport, TransportConfig } from './transport';
|
|
3
|
+
/**
|
|
4
|
+
* Carries the protocol over ordinary HTTP requests, for networks that permit HTTPS to the app's
|
|
5
|
+
* origin but refuse the WebSocket upgrade.
|
|
6
|
+
*
|
|
7
|
+
* Split-duplex: a long-lived `GET` carries server-to-client and short `POST`s carry
|
|
8
|
+
* client-to-server, correlated by a client-minted `sid`. Both legs address one channel that lives on
|
|
9
|
+
* the ikon server, so a proxy in between only has to relay bytes.
|
|
10
|
+
*
|
|
11
|
+
* The encoding ladder is internal: the endpoint selector sees one transport, and `connect()` does not
|
|
12
|
+
* resolve until an encoding has actually delivered a server message.
|
|
13
|
+
*/
|
|
14
|
+
export declare class HttpStreamTransport implements Transport {
|
|
15
|
+
private readonly framer;
|
|
16
|
+
private readonly callbacks;
|
|
17
|
+
private readonly sessionId;
|
|
18
|
+
private readonly keepaliveTimeoutMs;
|
|
19
|
+
private readonly connectionTimeoutMs;
|
|
20
|
+
private readonly pinnedMode;
|
|
21
|
+
private readonly preferredMode;
|
|
22
|
+
private baseUri;
|
|
23
|
+
private sid;
|
|
24
|
+
private mode;
|
|
25
|
+
private downstreamAbort;
|
|
26
|
+
private keepaliveTimeout;
|
|
27
|
+
private keepaliveResponseMessage;
|
|
28
|
+
private isClosed;
|
|
29
|
+
private connected;
|
|
30
|
+
private connecting;
|
|
31
|
+
private readonly sendQueue;
|
|
32
|
+
private sendPumpRunning;
|
|
33
|
+
private firstMessageResolver;
|
|
34
|
+
constructor(config: TransportConfig);
|
|
35
|
+
get isConnected(): boolean;
|
|
36
|
+
/** Which encoding is carrying this connection. For diagnostics and the benchmark harness. */
|
|
37
|
+
get activeMode(): HttpStreamMode;
|
|
38
|
+
connect(uri: string, authTicket: Uint8Array): Promise<void>;
|
|
39
|
+
send(message: ProtocolMessage): void;
|
|
40
|
+
close(): void;
|
|
41
|
+
/**
|
|
42
|
+
* Open one mode: create and authenticate the channel, then wait for the server's first message.
|
|
43
|
+
*
|
|
44
|
+
* One deadline covers both legs, and aborting the controller is what ends either, so a mode that
|
|
45
|
+
* stalls — on the opening POST as readily as on the stream that follows it — costs this much and
|
|
46
|
+
* no more. Three of these fit inside a normal transport timeout; a caller that configures a shorter
|
|
47
|
+
* one gets its budget honoured per mode. The controller is the one `close()` aborts, so a transport
|
|
48
|
+
* closed mid-attempt takes the request in flight down with it.
|
|
49
|
+
*/
|
|
50
|
+
private openMode;
|
|
51
|
+
/**
|
|
52
|
+
* Create the channel on the server and authenticate it, before anything streams.
|
|
53
|
+
*
|
|
54
|
+
* The ticket rides the body of a POST so that neither leg is a request a browser has to preflight:
|
|
55
|
+
* `text/plain` is CORS-safelisted, and with no custom header anywhere there is nothing left for a
|
|
56
|
+
* network that blocks `OPTIONS` — or strips headers it does not know — to break. It costs the
|
|
57
|
+
* round trip a preflight would have cost anyway, and unlike a preflight it cannot be refused.
|
|
58
|
+
*
|
|
59
|
+
* This is the same order a WebSocket uses: open, then send the ticket first. Only the leg carrying
|
|
60
|
+
* it differs, because a GET has no body to put it in.
|
|
61
|
+
*/
|
|
62
|
+
private openChannel;
|
|
63
|
+
/**
|
|
64
|
+
* Open one downstream attempt in a given encoding and wait for the server's first message.
|
|
65
|
+
*
|
|
66
|
+
* Resolving on the first message rather than on the response headers is the same liveness gate the
|
|
67
|
+
* WebSocket transport uses, and here it does double duty: it is also what detects the buffering
|
|
68
|
+
* proxy this ladder exists for, which answers the headers immediately and then delivers nothing.
|
|
69
|
+
*/
|
|
70
|
+
private openDownstream;
|
|
71
|
+
/**
|
|
72
|
+
* Read one downstream response to its end, then decide whether another follows.
|
|
73
|
+
*
|
|
74
|
+
* A streaming response ending means the connection died; a poll response ending is how poll mode
|
|
75
|
+
* works, so it re-issues immediately.
|
|
76
|
+
*/
|
|
77
|
+
private runDownstreamLoop;
|
|
78
|
+
private readResponse;
|
|
79
|
+
/**
|
|
80
|
+
* Keep exactly one upstream request in flight, carrying everything queued behind it.
|
|
81
|
+
*
|
|
82
|
+
* One at a time so the server sees the client's messages in the order it produced them — parallel
|
|
83
|
+
* requests have no ordering guarantee — and batching so a burst costs one request rather than one
|
|
84
|
+
* each.
|
|
85
|
+
*/
|
|
86
|
+
private runSendPump;
|
|
87
|
+
/**
|
|
88
|
+
* Concatenate queued messages into one body, stopping before the batch cap.
|
|
89
|
+
*
|
|
90
|
+
* A message is never split: the length prefix is what frames the batch on the far side, so the
|
|
91
|
+
* cap gives way to a single oversized message rather than the other way round.
|
|
92
|
+
*/
|
|
93
|
+
private takeBatch;
|
|
94
|
+
private streamUrl;
|
|
95
|
+
/**
|
|
96
|
+
* The opening POST carries the encoding too: the channel is built once, and a poll channel behaves
|
|
97
|
+
* differently from a streaming one, so it has to know which it is before the GET arrives.
|
|
98
|
+
*/
|
|
99
|
+
private openUrl;
|
|
100
|
+
private sendUrl;
|
|
101
|
+
private getKeepaliveResponse;
|
|
102
|
+
private handleProtocolMessage;
|
|
103
|
+
private handleClose;
|
|
104
|
+
private abortDownstream;
|
|
105
|
+
private resetKeepaliveTimeout;
|
|
106
|
+
private clearKeepaliveTimeout;
|
|
107
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cuts a byte stream back into protocol messages.
|
|
3
|
+
*
|
|
4
|
+
* Every protocol message opens with its own little-endian `int Length`, so a stream of concatenated
|
|
5
|
+
* messages is self-framing and needs no envelope. Both stream transports — WebTransport and the HTTP
|
|
6
|
+
* stream — receive exactly those bytes, so they share this rather than each carrying a copy of the
|
|
7
|
+
* same buffer arithmetic.
|
|
8
|
+
*
|
|
9
|
+
* Grow-only buffer with offset/length tracking, and a cached `DataView`, to keep a busy connection
|
|
10
|
+
* from allocating per message.
|
|
11
|
+
*/
|
|
12
|
+
export declare class MessageFramer {
|
|
13
|
+
private buffer;
|
|
14
|
+
private bufferOffset;
|
|
15
|
+
private bufferLength;
|
|
16
|
+
private dataView;
|
|
17
|
+
private dataViewBuffer;
|
|
18
|
+
/**
|
|
19
|
+
* Append received bytes and hand every message they complete to `onMessage`.
|
|
20
|
+
*
|
|
21
|
+
* The `Uint8Array` passed to `onMessage` is a view into the internal buffer, valid only until the
|
|
22
|
+
* next `push`. A handler that keeps it must copy it.
|
|
23
|
+
*
|
|
24
|
+
* @throws when the stream carries a length no protocol message could have, which means the bytes
|
|
25
|
+
* are not a protocol stream at all and nothing later in it can be trusted.
|
|
26
|
+
*/
|
|
27
|
+
push(data: Uint8Array, onMessage: (message: Uint8Array) => void): void;
|
|
28
|
+
/** Drop everything buffered, keeping the allocation for reuse across a reconnect. */
|
|
29
|
+
reset(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Append incoming data using a grow-only strategy, compacting when the data fits but needs
|
|
32
|
+
* repositioning.
|
|
33
|
+
*/
|
|
34
|
+
private append;
|
|
35
|
+
private getDataView;
|
|
36
|
+
}
|
package/transport/transport.d.ts
CHANGED
|
@@ -1,4 +1,12 @@
|
|
|
1
1
|
import { ProtocolMessage } from '../../shared/protocol/src/index.ts';
|
|
2
|
+
/**
|
|
3
|
+
* The HTTP stream transport's downstream encodings, most efficient first.
|
|
4
|
+
*
|
|
5
|
+
* Declared here, on the leaf every transport already imports, so the one union is not respelled in
|
|
6
|
+
* the transport, the channel, the worker, the client and the query parameters — five copies that
|
|
7
|
+
* have to be edited together to add an encoding.
|
|
8
|
+
*/
|
|
9
|
+
export type HttpStreamMode = 'binary' | 'sse' | 'poll';
|
|
2
10
|
/**
|
|
3
11
|
* Transport interface for Ikon server connections.
|
|
4
12
|
* Designed to support both WebSocket and WebTransport implementations.
|
|
@@ -65,4 +73,16 @@ export interface TransportConfig {
|
|
|
65
73
|
* If not specified, transports use their own defaults (10s).
|
|
66
74
|
*/
|
|
67
75
|
connectionTimeoutMs?: number;
|
|
76
|
+
/**
|
|
77
|
+
* Pins the HTTP stream transport to one downstream encoding instead of letting it walk its
|
|
78
|
+
* ladder. Comes from `?ikon-transport=http-<encoding>`, read on the main thread — a transport
|
|
79
|
+
* running inside the protocol worker has no `window` to read it from.
|
|
80
|
+
*/
|
|
81
|
+
httpStreamMode?: HttpStreamMode;
|
|
82
|
+
/**
|
|
83
|
+
* The encoding to start the HTTP stream's ladder at, learned from a previous connection on this
|
|
84
|
+
* device. Unlike {@link httpStreamMode} it is a starting point rather than a pin: the remaining
|
|
85
|
+
* encodings are still tried if it fails.
|
|
86
|
+
*/
|
|
87
|
+
httpStreamPreferredMode?: HttpStreamMode;
|
|
68
88
|
}
|
|
@@ -22,11 +22,7 @@ export declare class WebTransportTransport implements Transport {
|
|
|
22
22
|
private keepaliveTimeout;
|
|
23
23
|
private readLoopActive;
|
|
24
24
|
private isClosed;
|
|
25
|
-
private
|
|
26
|
-
private receiveBufferOffset;
|
|
27
|
-
private receiveBufferLength;
|
|
28
|
-
private receiveDataView;
|
|
29
|
-
private receiveDataViewBuffer;
|
|
25
|
+
private readonly framer;
|
|
30
26
|
private keepaliveResponseMessage;
|
|
31
27
|
private firstMessageResolver;
|
|
32
28
|
private firstMessageRejecter;
|
|
@@ -43,25 +39,10 @@ export declare class WebTransportTransport implements Transport {
|
|
|
43
39
|
* Start the read loop to receive messages.
|
|
44
40
|
*/
|
|
45
41
|
private startReadLoop;
|
|
46
|
-
/**
|
|
47
|
-
* Append incoming data to the receive buffer using grow-only strategy.
|
|
48
|
-
* Compacts when offset exceeds half capacity and data is sparse.
|
|
49
|
-
*/
|
|
50
|
-
private appendToBuffer;
|
|
51
|
-
/**
|
|
52
|
-
* Get or create a cached DataView for the receive buffer.
|
|
53
|
-
*/
|
|
54
|
-
private getReceiveDataView;
|
|
55
42
|
/**
|
|
56
43
|
* Get or create a cached keepalive response message.
|
|
57
44
|
*/
|
|
58
45
|
private getKeepaliveResponse;
|
|
59
|
-
/**
|
|
60
|
-
* Process complete messages from the receive buffer.
|
|
61
|
-
* Protocol messages start with a 4-byte little-endian length field.
|
|
62
|
-
* Uses subarray views to avoid per-message allocations.
|
|
63
|
-
*/
|
|
64
|
-
private processBufferedMessages;
|
|
65
46
|
/**
|
|
66
47
|
* Handle incoming protocol message.
|
|
67
48
|
*/
|
|
@@ -26,15 +26,6 @@ export interface EmbeddedOAuthResult {
|
|
|
26
26
|
provider: string;
|
|
27
27
|
codeVerifier: string | null;
|
|
28
28
|
}
|
|
29
|
-
/**
|
|
30
|
-
* Carries the verifier back to the frame on its own URL, beside the code.
|
|
31
|
-
*
|
|
32
|
-
* It has to travel because the frame that minted it does not survive the embedder's navigation, and
|
|
33
|
-
* returns on a different origin whenever its address is assigned per session — so the sessionStorage
|
|
34
|
-
* it wrote to is not the one it can read. Same-origin, spent immediately, and stripped from the
|
|
35
|
-
* address bar with the rest of the callback params.
|
|
36
|
-
*/
|
|
37
|
-
export declare const PKCE_URL_PARAM = "ikon_pkce";
|
|
38
29
|
/**
|
|
39
30
|
* True when this document is nested in another. A cross-origin parent makes the property access
|
|
40
31
|
* itself throw, which is the embedded case too.
|
package/utils/log-sender.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export declare function startLogSender(backendUrl: string, authToken: string): void;
|
|
2
|
+
export declare function refreshLogSenderAuthToken(authToken: string): void;
|
|
2
3
|
export declare function sendAnalyticsEvent(eventName: string, parameters: Record<string, string>): void;
|
|
3
4
|
export declare function stopLogSender(): void;
|
package/utils/query-params.d.ts
CHANGED
|
@@ -1,75 +1,100 @@
|
|
|
1
|
+
import { HttpStreamMode } from '../transport/transport';
|
|
1
2
|
/**
|
|
2
3
|
* SDK Query Parameters
|
|
3
4
|
*
|
|
4
|
-
* All SDK-internal query params use the "ikon-" prefix to avoid conflicts with
|
|
5
|
-
*
|
|
6
|
-
*
|
|
5
|
+
* All SDK-internal query params use the "ikon-" prefix to avoid conflicts with client application
|
|
6
|
+
* query params. Both "-" and "_" word separators are accepted (e.g., "ikon-proxy" and "ikon_proxy"
|
|
7
|
+
* both work).
|
|
8
|
+
*
|
|
9
|
+
* Every `ikon-*` parameter the SDK reads is declared here. One read anywhere else is a defect:
|
|
10
|
+
* nothing enumerates them, so a stray parameter is invisible to this list, to the docs generated
|
|
11
|
+
* from it, and to anyone deciding whether a name is free.
|
|
7
12
|
*
|
|
8
13
|
* Supported parameters:
|
|
9
|
-
* - ikon-proxy
|
|
10
|
-
*
|
|
11
|
-
* - ikon-
|
|
12
|
-
* - ikon-
|
|
13
|
-
* - ikon-
|
|
14
|
-
* - ikon-
|
|
15
|
-
* - ikon-
|
|
16
|
-
* - ikon-
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* - ikon-
|
|
20
|
-
* - ikon-
|
|
21
|
-
* - ikon-
|
|
22
|
-
* - ikon-
|
|
23
|
-
* - ikon-
|
|
24
|
-
* - ikon-
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
14
|
+
* - ikon-proxy Pin the connect tier: false | true (on-host proxy) | lb (alias: stream, fleet gateway)
|
|
15
|
+
* - ikon-transport Pin the transport: ws | wt | http | http-binary | http-sse | http-poll (long forms accepted)
|
|
16
|
+
* - ikon-connect External connect target: <token> | <port>~<token> | <full-url>. Carries a credential
|
|
17
|
+
* - ikon-session Join the live session with this sessionIdentityHash; no live session is an error
|
|
18
|
+
* - ikon-same-origin Route API and auth through the app's own origin; default on in cloud, off in local dev
|
|
19
|
+
* - ikon-debug Enable SDK debug logging
|
|
20
|
+
* - ikon-debug-overlay Show the on-screen debug overlay; ikon-debug does not imply it
|
|
21
|
+
* - ikon-inspect Enable the element inspection overlay
|
|
22
|
+
* - ikon-lang Override language detection (e.g. "en", "fi")
|
|
23
|
+
* - ikon-audio Force audio on or off
|
|
24
|
+
* - ikon-video Force video on or off
|
|
25
|
+
* - ikon-webrtc Force WebRTC on or off
|
|
26
|
+
* - ikon-ice-transport WebRTC ICE policy: relay (TURN only) | all
|
|
27
|
+
* - ikon-retry Retry loops in auth/channel connect; false fails fast (default true)
|
|
28
|
+
* - ikon-snapshot Connect as a build-time snapshot client; sets Context.IsSnapshot
|
|
29
|
+
* - ikon-signed-out The user signed out; suppresses auto-login for this load
|
|
30
|
+
*
|
|
31
|
+
* OAuth callback parameters, underscore form only. The auth backend sets these on its redirect
|
|
32
|
+
* (backend/libs/auth/user/src/lib/redirect.service.ts), so the names are a wire contract:
|
|
33
|
+
* - ikon_token Session token from a completed OAuth round-trip
|
|
34
|
+
* - ikon_code Authorization code from a completed OAuth round-trip
|
|
35
|
+
* - ikon_provider Which provider answered
|
|
36
|
+
* - ikon_pkce PKCE verifier handed to an embedded frontend
|
|
28
37
|
*/
|
|
29
38
|
export declare const IKON_PARAM_PROXY = "ikon-proxy";
|
|
30
|
-
export declare const
|
|
31
|
-
export declare const
|
|
39
|
+
export declare const IKON_PARAM_TRANSPORT = "ikon-transport";
|
|
40
|
+
export declare const IKON_PARAM_CONNECT = "ikon-connect";
|
|
41
|
+
export declare const IKON_PARAM_SESSION = "ikon-session";
|
|
42
|
+
export declare const IKON_PARAM_SAME_ORIGIN = "ikon-same-origin";
|
|
32
43
|
export declare const IKON_PARAM_DEBUG = "ikon-debug";
|
|
44
|
+
export declare const IKON_PARAM_DEBUG_OVERLAY = "ikon-debug-overlay";
|
|
45
|
+
export declare const IKON_PARAM_INSPECT = "ikon-inspect";
|
|
33
46
|
export declare const IKON_PARAM_LANG = "ikon-lang";
|
|
34
|
-
export declare const IKON_PARAM_SERVER_URL = "ikon-server-url";
|
|
35
|
-
export declare const IKON_PARAM_CONNECT = "ikon-connect";
|
|
36
47
|
export declare const IKON_PARAM_AUDIO = "ikon-audio";
|
|
37
48
|
export declare const IKON_PARAM_VIDEO = "ikon-video";
|
|
38
49
|
export declare const IKON_PARAM_WEBRTC = "ikon-webrtc";
|
|
39
50
|
export declare const IKON_PARAM_ICE_TRANSPORT = "ikon-ice-transport";
|
|
40
|
-
export declare const IKON_PARAM_INSPECT = "ikon-inspect";
|
|
41
|
-
export declare const IKON_PARAM_DEBUG_OVERLAY = "ikon-debug-overlay";
|
|
42
|
-
export declare const IKON_PARAM_AUTH = "ikon-auth";
|
|
43
51
|
export declare const IKON_PARAM_RETRY = "ikon-retry";
|
|
44
|
-
export declare const IKON_PARAM_API = "ikon-api";
|
|
45
52
|
export declare const IKON_PARAM_SNAPSHOT = "ikon-snapshot";
|
|
46
|
-
export declare const
|
|
53
|
+
export declare const IKON_PARAM_SIGNED_OUT = "ikon-signed-out";
|
|
54
|
+
export declare const IKON_PARAM_OAUTH_TOKEN = "ikon_token";
|
|
55
|
+
export declare const IKON_PARAM_OAUTH_CODE = "ikon_code";
|
|
56
|
+
export declare const IKON_PARAM_OAUTH_PROVIDER = "ikon_provider";
|
|
57
|
+
export declare const IKON_PARAM_OAUTH_PKCE = "ikon_pkce";
|
|
47
58
|
/**
|
|
48
59
|
* Set an SDK query parameter in the URL via history.replaceState.
|
|
49
60
|
*/
|
|
50
61
|
export declare function setSdkUrlParam(canonicalName: string, value: string): void;
|
|
51
|
-
export declare function getProxyParam(): boolean | null;
|
|
52
62
|
/**
|
|
53
|
-
* Which connect tier to pin
|
|
54
|
-
* is one thing to remember and one thing to document.
|
|
63
|
+
* Which connect tier to pin.
|
|
55
64
|
*
|
|
56
65
|
* `lb` (and the friendlier alias `stream`) is what makes the same-origin stream tier testable at
|
|
57
66
|
* all: in `auto` mode a client only reaches it after failing the two above it, which is close to
|
|
58
67
|
* impossible to arrange deliberately.
|
|
59
68
|
*/
|
|
60
69
|
export declare function getProxyTierParam(): 'direct' | 'proxy' | 'lb' | null;
|
|
61
|
-
|
|
62
|
-
export
|
|
70
|
+
/** The transport families a session can be pinned to. */
|
|
71
|
+
export type TransportFamily = 'websocket' | 'webtransport' | 'httpstream';
|
|
72
|
+
/** What {@link getTransportParam} resolved: a family, and for the HTTP stream an optional encoding. */
|
|
73
|
+
export interface PinnedTransport {
|
|
74
|
+
family: TransportFamily;
|
|
75
|
+
mode?: HttpStreamMode;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Pin one transport, and optionally its encoding — `?ikon-transport=http-poll`.
|
|
79
|
+
*
|
|
80
|
+
* The single parameter is the whole surface: pinning a family turns the others off, and naming an
|
|
81
|
+
* encoding after it pins that too. Testing a fallback path is exactly when nobody wants to remember
|
|
82
|
+
* which combination of flags adds up to one transport.
|
|
83
|
+
*
|
|
84
|
+
* Returns null for anything unrecognised, which leaves the ladder alone: a typo must not silently
|
|
85
|
+
* pin the slowest transport.
|
|
86
|
+
*/
|
|
87
|
+
export declare function getTransportParam(): PinnedTransport | null;
|
|
63
88
|
export declare function getDebugParam(): boolean;
|
|
64
89
|
export declare function getLangParam(): string | null;
|
|
65
|
-
export declare function getServerUrlParam(): string | null;
|
|
66
90
|
/**
|
|
67
|
-
* The
|
|
91
|
+
* The external connect URL a shareable preview link carries.
|
|
68
92
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
93
|
+
* Three forms, because a preview's frontend is usually served by the Ikon server itself and the link
|
|
94
|
+
* then needs to carry only the token:
|
|
95
|
+
* - `<token>` — same host and port as the page
|
|
96
|
+
* - `<port>~<token>` — same host, different port
|
|
97
|
+
* - `<full-url>` — anywhere else, the only form that can name a different host
|
|
73
98
|
*
|
|
74
99
|
* Returns null when the parameter is absent, so a caller can fall back.
|
|
75
100
|
*/
|
|
@@ -92,15 +117,19 @@ export declare function getInspectParam(): boolean;
|
|
|
92
117
|
*/
|
|
93
118
|
export declare function getDebugOverlayParam(): boolean;
|
|
94
119
|
/**
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
*
|
|
120
|
+
* Whether backend calls — the API and auth alike — go through the app's own origin (`/ikon/api`,
|
|
121
|
+
* `/ikon/auth`) rather than the cross-origin platform hosts.
|
|
122
|
+
*
|
|
123
|
+
* One switch for both, and one default: same origin wherever the app is deployed. The app's origin
|
|
124
|
+
* is already trusted by the client that loaded the app, so nothing there carries a cross-origin
|
|
125
|
+
* cert or CORS surface — which is also what fixes old devices (smart-TV browsers) that do not trust
|
|
126
|
+
* the standalone hosts' certificates. The two surfaces answer it identically, so there is nothing a
|
|
127
|
+
* parameter each could express that this cannot.
|
|
128
|
+
*
|
|
129
|
+
* Returns null when unset, so the caller applies the default rather than this deciding for it.
|
|
100
130
|
*/
|
|
101
|
-
export declare function
|
|
131
|
+
export declare function getSameOriginParam(): boolean | null;
|
|
102
132
|
export declare function getRetryParam(): boolean;
|
|
103
|
-
export declare function getApiParam(): boolean | null;
|
|
104
133
|
/**
|
|
105
134
|
* Connect as a build-time snapshot client (`?ikon-snapshot=true`). Sets `Context.IsSnapshot` so
|
|
106
135
|
* the app / Parallax can render in snapshot mode. A dev affordance for tuning the boot-snapshot UI.
|
|
@@ -112,3 +141,10 @@ export declare function getSnapshotParam(): boolean;
|
|
|
112
141
|
* fails the connect when none is live rather than quietly starting a fresh one.
|
|
113
142
|
*/
|
|
114
143
|
export declare function getSessionParam(): string | null;
|
|
144
|
+
/**
|
|
145
|
+
* Whether this load followed an explicit sign-out (`?ikon-signed-out`).
|
|
146
|
+
*
|
|
147
|
+
* A valueless flag, so presence is the whole signal: it suppresses the automatic login that would
|
|
148
|
+
* otherwise put the user straight back into the session they just left.
|
|
149
|
+
*/
|
|
150
|
+
export declare function getSignedOutParam(): boolean;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
function e(e){return e}function t(e){if(e.length<8)throw Error(`Protocol message too short`);return(e[4]|e[5]<<8|e[6]<<16|e[7]<<24)>>>0}function n(e){return t(e)&4294901760}function r(e){let t=ee(e),n=new DataView(t.buffer,t.byteOffset,t.byteLength);if(t.length<27)throw Error(`Protocol payload too short`);let r=n.getUint32(0,!0),i=n.getUint32(4,!0),a=n.getUint32(8,!0),o=n.getUint32(12,!0),s=n.getUint32(16,!0),c=n.getUint32(20,!0),l=n.getUint8(24),u=n.getUint8(25),d=n.getUint8(26);if(27+c*4>t.length)throw Error(`Protocol header exceeds payload length`);let f=[],p=27;for(let e=0;e<c;e++)f.push(n.getUint32(p,!0)),p+=4;return{length:r,opcode:i,senderId:a,trackId:o,sequenceId:s,targetIds:f,payloadVersion:l,payloadType:u,flags:d}}function i(t,n,r,i,a){let o=a?.trackId??0,s=a?.sequenceId??0,c=a?.flags??0,l=a?.targetIds??[],u=a?.payloadType??8,d=27+l.length*4,f=d+n.length,p=new Uint8Array(f),m=new DataView(p.buffer);m.setUint32(0,f,!0),m.setUint32(4,t>>>0,!0),m.setUint32(8,i>>>0,!0),m.setUint32(12,o>>>0,!0),m.setUint32(16,s>>>0,!0),m.setUint32(20,l.length>>>0,!0),m.setUint8(24,r&255),m.setUint8(25,u&255),m.setUint8(26,c&255);let h=27;for(let e=0;e<l.length;e++)m.setUint32(h,l[e]>>>0,!0),h+=4;return p.set(n,d),e(p)}let a=function(e){return e[e.Null=1]=`Null`,e[e.Bool=2]=`Bool`,e[e.Int32=3]=`Int32`,e[e.Int64=4]=`Int64`,e[e.UInt32=5]=`UInt32`,e[e.UInt64=6]=`UInt64`,e[e.Float32=7]=`Float32`,e[e.Float64=8]=`Float64`,e[e.Array=9]=`Array`,e[e.Dict=10]=`Dict`,e[e.Object=11]=`Object`,e[e.String=12]=`String`,e[e.Binary=13]=`Binary`,e[e.Guid=14]=`Guid`,e}({});const o=new TextEncoder;new TextDecoder(`utf-8`,{fatal:!0});var s=class e{buffer=new f;cached;constructor(e=1){this.buffer.writeByte(161),this.buffer.writeVarUInt(e>>>0)}writeInt32Field(e,t){this.writeFixedField(e,3,()=>this.buffer.writeInt32(t|0))}writeUInt32Field(e,t){this.writeFixedField(e,5,()=>this.buffer.writeUInt32(t>>>0))}writeInt64Field(e,t){this.writeFixedField(e,4,()=>this.buffer.writeBigInt64(t))}writeUInt64Field(e,t){this.writeFixedField(e,6,()=>this.buffer.writeBigUInt64(t))}writeFloat32Field(e,t){this.writeFixedField(e,7,()=>this.buffer.writeFloat32(t))}writeFloat64Field(e,t){this.writeFixedField(e,8,()=>this.buffer.writeFloat64(t))}writeBoolField(e,t){this.writeFixedField(e,2,()=>this.buffer.writeByte(+!!t))}writeGuidField(e,t){let n=t instanceof d?t.asBytes():t;if(n.length!==16)throw Error(`Guid payload must be 16 bytes`);this.writeFixedField(e,14,()=>this.buffer.writeBytes(n))}writeStringField(e,t){let n=o.encode(t??``);this.writeVariableField(e,12,n)}writeBinaryField(e,t){this.writeVariableField(e,13,t)}writeObjectField(t,n,r){let i=new e(n);r(i);let a=i.finish();this.writeVariableField(t,11,a)}writeArrayField(e,t,n){let r=new c(t);n(r);let i=r.finish();this.writeVariableField(e,9,i)}writeDictionaryField(e,t,n,r){let i=new l(t,n);r(i);let a=i.finish();this.writeVariableField(e,10,a)}finish(){return this.cached||=(this.buffer.writeByte(162),this.buffer.toUint8Array()),this.cached}writeFixedField(e,t,n){this.writeFieldHeader(e,t,0),n()}writeVariableField(e,t,n){this.writeFieldHeader(e,t,n.length),this.buffer.writeBytes(n)}writeFieldHeader(e,t,n){this.buffer.writeUInt32(e>>>0),this.buffer.writeByte(p(t)),m(t)&&this.buffer.writeVarUInt(n>>>0)}},c=class e{elementType;payload=new f;count=0;constructor(e){this.elementType=e}writeInt32(e){this.ensureElementType(3),this.count++,this.payload.writeInt32(e|0)}writeUInt32(e){this.ensureElementType(5),this.count++,this.payload.writeUInt32(e>>>0)}writeInt64(e){this.ensureElementType(4),this.count++,this.payload.writeBigInt64(e)}writeUInt64(e){this.ensureElementType(6),this.count++,this.payload.writeBigUInt64(e)}writeFloat32(e){this.ensureElementType(7),this.count++,this.payload.writeFloat32(e)}writeFloat64(e){this.ensureElementType(8),this.count++,this.payload.writeFloat64(e)}writeBool(e){this.ensureElementType(2),this.count++,this.payload.writeByte(+!!e)}writeGuid(e){this.ensureElementType(14),this.count++;let t=e instanceof d?e.asBytes():e;if(t.length!==16)throw Error(`Guid payload must be 16 bytes`);this.payload.writeBytes(t)}writeString(e){this.ensureElementType(12),this.count++;let t=o.encode(e??``);this.payload.writeVarUInt(t.length),this.payload.writeBytes(t)}writeBinary(e){this.ensureElementType(13),this.count++,this.payload.writeVarUInt(e.length),this.payload.writeBytes(e)}writeObject(e,t){this.ensureElementType(11),this.count++;let n=new s(e);t(n);let r=n.finish();this.payload.writeVarUInt(r.length),this.payload.writeBytes(r)}writeArray(t,n){this.ensureElementType(9),this.count++;let r=new e(t);n(r);let i=r.finish();this.payload.writeBytes(i)}writeDictionary(e,t,n){this.ensureElementType(10),this.count++;let r=new l(e,t);n(r);let i=r.finish();this.payload.writeBytes(i)}finish(){let e=new f;return e.writeByte(p(this.elementType)),e.writeVarUInt(this.count),e.writeBytes(this.payload.toUint8Array()),e.toUint8Array()}ensureElementType(e){if(this.elementType!==e)throw Error(`Array element type is ${a[this.elementType]}, expected ${a[e]}`)}},l=class{keyType;valueType;payload=new f;count=0;entryOpen=!1;constructor(e,t){this.keyType=e,this.valueType=t,h(e)}beginEntry(){if(this.entryOpen)throw Error(`Previous dictionary entry not completed`);return this.count++,this.entryOpen=!0,new u(this.keyType,this.valueType,this.payload,()=>{this.entryOpen=!1})}finish(){if(this.entryOpen)throw Error(`Dictionary entry not completed`);let e=new f;return e.writeByte(p(this.keyType)),e.writeByte(p(this.valueType)),e.writeVarUInt(this.count),e.writeBytes(this.payload.toUint8Array()),e.toUint8Array()}},u=class{keyType;valueType;payload;onComplete;keyWritten=!1;valueWritten=!1;completed=!1;constructor(e,t,n,r){this.keyType=e,this.valueType=t,this.payload=n,this.onComplete=r}writeKeyInt32(e){this.ensureKeyType(3),this.payload.writeInt32(e|0),this.keyWritten=!0}writeKeyUInt32(e){this.ensureKeyType(5),this.payload.writeUInt32(e>>>0),this.keyWritten=!0}writeKeyInt64(e){this.ensureKeyType(4),this.payload.writeBigInt64(e),this.keyWritten=!0}writeKeyUInt64(e){this.ensureKeyType(6),this.payload.writeBigUInt64(e),this.keyWritten=!0}writeKeyFloat32(e){this.ensureKeyType(7),this.payload.writeFloat32(e),this.keyWritten=!0}writeKeyFloat64(e){this.ensureKeyType(8),this.payload.writeFloat64(e),this.keyWritten=!0}writeKeyBool(e){this.ensureKeyType(2),this.payload.writeByte(+!!e),this.keyWritten=!0}writeKeyGuid(e){this.ensureKeyType(14);let t=e instanceof d?e.asBytes():e;if(t.length!==16)throw Error(`Guid payload must be 16 bytes`);this.payload.writeBytes(t),this.keyWritten=!0}writeKeyString(e){this.ensureKeyType(12);let t=o.encode(e??``);this.payload.writeVarUInt(t.length),this.payload.writeBytes(t),this.keyWritten=!0}writeKeyBinary(e){this.ensureKeyType(13),this.payload.writeVarUInt(e.length),this.payload.writeBytes(e),this.keyWritten=!0}writeValueInt32(e){this.ensureValueType(3),this.payload.writeInt32(e|0),this.valueWritten=!0}writeValueUInt32(e){this.ensureValueType(5),this.payload.writeUInt32(e>>>0),this.valueWritten=!0}writeValueInt64(e){this.ensureValueType(4),this.payload.writeBigInt64(e),this.valueWritten=!0}writeValueUInt64(e){this.ensureValueType(6),this.payload.writeBigUInt64(e),this.valueWritten=!0}writeValueFloat32(e){this.ensureValueType(7),this.payload.writeFloat32(e),this.valueWritten=!0}writeValueFloat64(e){this.ensureValueType(8),this.payload.writeFloat64(e),this.valueWritten=!0}writeValueBool(e){this.ensureValueType(2),this.payload.writeByte(+!!e),this.valueWritten=!0}writeValueGuid(e){this.ensureValueType(14);let t=e instanceof d?e.asBytes():e;if(t.length!==16)throw Error(`Guid payload must be 16 bytes`);this.payload.writeBytes(t),this.valueWritten=!0}writeNullValue(){this.ensureValueType(1),this.valueWritten=!0}writeValueBinary(e){this.ensureValueType(13),this.payload.writeVarUInt(e.length),this.payload.writeBytes(e),this.valueWritten=!0}writeValueString(e){this.ensureValueType(12);let t=o.encode(e??``);this.payload.writeVarUInt(t.length),this.payload.writeBytes(t),this.valueWritten=!0}writeValueObject(e,t){this.ensureValueType(11);let n=new s(e);t(n);let r=n.finish();this.payload.writeVarUInt(r.length),this.payload.writeBytes(r),this.valueWritten=!0}writeValueArray(e,t){this.ensureValueType(9);let n=new c(e);t(n);let r=n.finish();this.payload.writeBytes(r),this.valueWritten=!0}writeValueDictionary(e,t,n){this.ensureValueType(10);let r=new l(e,t);n(r);let i=r.finish();this.payload.writeBytes(i),this.valueWritten=!0}complete(){if(!this.completed){if(!this.keyWritten||!this.valueWritten)throw Error(`Dictionary entry must write both key and value`);this.completed=!0,this.onComplete()}}ensureKeyType(e){if(this.keyType!==e)throw Error(`Dictionary key type is ${a[this.keyType]}, expected ${a[e]}`)}ensureValueType(e){if(this.valueType!==e)throw Error(`Dictionary value type is ${a[this.valueType]}, expected ${a[e]}`)}},d=class e{bytes;constructor(e){this.bytes=e}static fromString(t){if(!t)throw Error(`Guid string is empty`);let n=t.replace(/-/g,``);if(n.length!==32)throw Error(`Guid string must be 32 hex characters`);let r=new Uint8Array(16),i=e.parseHexSlice(n,0,8),a=e.parseHexSlice(n,8,4),o=e.parseHexSlice(n,12,4);e.writeUInt32LE(r,0,i),e.writeUInt16LE(r,4,a),e.writeUInt16LE(r,6,o);for(let t=0;t<8;t++)r[8+t]=e.parseHexSlice(n,16+t*2,2);return new e(r)}static fromBytes(t){if(t.length!==16)throw Error(`Guid byte array must be 16 bytes`);return new e(Uint8Array.from(t))}static createZero(){return new e(new Uint8Array(16))}static createRandom(){let t=new Uint8Array(16),n=globalThis.crypto;if(n?.getRandomValues)n.getRandomValues(t);else for(let e=0;e<t.length;e++)t[e]=Math.floor(Math.random()*256);return t[6]=t[6]&15|64,t[8]=t[8]&63|128,new e(t)}toString(){let t=this.bytes;return[e.toHex(e.readUInt32LE(t,0),8),e.toHex(e.readUInt16LE(t,4),4),e.toHex(e.readUInt16LE(t,6),4),g(t.subarray(8,10)),g(t.subarray(10,16))].join(`-`)}asBytes(){return this.bytes.slice()}static parseHexSlice(e,t,n){let r=e.substr(t,n),i=Number.parseInt(r,16);if(Number.isNaN(i))throw Error(`Guid string contains invalid characters`);return i>>>0}static writeUInt32LE(e,t,n){let r=n>>>0;e[t]=r&255,e[t+1]=r>>>8&255,e[t+2]=r>>>16&255,e[t+3]=r>>>24&255}static writeUInt16LE(e,t,n){let r=n&65535;e[t]=r&255,e[t+1]=r>>>8&255}static readUInt32LE(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0}static readUInt16LE(e,t){return(e[t]|e[t+1]<<8)&65535}static toHex(e,t){return(e>>>0).toString(16).padStart(t,`0`)}},f=class e{static INITIAL_CAPACITY=256;buffer;dataView;length=0;constructor(){this.buffer=new Uint8Array(e.INITIAL_CAPACITY),this.dataView=new DataView(this.buffer.buffer)}ensureCapacity(e){let t=this.length+e;if(t<=this.buffer.length)return;let n=this.buffer.length;for(;n<t;)n*=2;let r=new Uint8Array(n);r.set(this.buffer.subarray(0,this.length)),this.buffer=r,this.dataView=new DataView(this.buffer.buffer)}writeByte(e){this.ensureCapacity(1),this.buffer[this.length++]=e&255}writeBytes(e){this.ensureCapacity(e.length),this.buffer.set(e,this.length),this.length+=e.length}writeUInt32(e){this.ensureCapacity(4),this.dataView.setUint32(this.length,e>>>0,!0),this.length+=4}writeInt32(e){this.ensureCapacity(4),this.dataView.setInt32(this.length,e|0,!0),this.length+=4}writeFloat32(e){this.ensureCapacity(4),this.dataView.setFloat32(this.length,e,!0),this.length+=4}writeFloat64(e){this.ensureCapacity(8),this.dataView.setFloat64(this.length,e,!0),this.length+=8}writeBigInt64(e){this.ensureCapacity(8),this.dataView.setBigInt64(this.length,e,!0),this.length+=8}writeBigUInt64(e){this.ensureCapacity(8),this.dataView.setBigUint64(this.length,e,!0),this.length+=8}writeVarUInt(e){let t=e>>>0;for(;t>=128;)this.ensureCapacity(1),this.buffer[this.length++]=t&127|128,t>>>=7;this.ensureCapacity(1),this.buffer[this.length++]=t&127}toUint8Array(){return this.buffer.slice(0,this.length)}};function p(e,t=0){if(t&240)throw Error(`Teleport flags must fit into 4 bits`);return(e&15)<<4|t&15}function m(e){return e===12||e===13||e===9||e===11||e===10}function h(e){if(e===9||e===11||e===10||e===1)throw Error(`Dictionary keys must be primitive Teleport types`)}function g(e){return Array.from(e).map(e=>e.toString(16).padStart(2,`0`)).join(``)}function ee(e){return e instanceof Uint8Array?e:new Uint8Array(e)}let _=function(e){return e[e.None=0]=`None`,e[e.WebSocket=1]=`WebSocket`,e[e.WebSocketProxy=2]=`WebSocketProxy`,e[e.WebTransport=4]=`WebTransport`,e[e.WebTransportProxy=8]=`WebTransportProxy`,e[e.Tcp=16]=`Tcp`,e[e.TcpProxy=32]=`TcpProxy`,e[e.Https=64]=`Https`,e[e.WebRTC=128]=`WebRTC`,e[e.TcpTls=256]=`TcpTls`,e[e.Udp=512]=`Udp`,e[e.UdpDtls=1024]=`UdpDtls`,e}({}),v=function(e){return e[e.NONE=0]=`NONE`,e[e.CONSTANT_GROUP_BITS=15]=`CONSTANT_GROUP_BITS`,e[e.CONSTANT_GROUP_OFFSET=16]=`CONSTANT_GROUP_OFFSET`,e[e.GROUP_CORE=65536]=`GROUP_CORE`,e[e.CORE_AUTH_RESPONSE=65537]=`CORE_AUTH_RESPONSE`,e[e.CORE_AUTH_TICKET=65538]=`CORE_AUTH_TICKET`,e[e.CORE_GLOBAL_STATE=65539]=`CORE_GLOBAL_STATE`,e[e.CORE_ON_SERVER_STATUS_PING=65540]=`CORE_ON_SERVER_STATUS_PING`,e[e.CORE_ON_USER_JOINED=65541]=`CORE_ON_USER_JOINED`,e[e.CORE_ON_USER_LEFT=65542]=`CORE_ON_USER_LEFT`,e[e.CORE_ON_CLIENT_JOINED=65543]=`CORE_ON_CLIENT_JOINED`,e[e.CORE_ON_CLIENT_LEFT=65544]=`CORE_ON_CLIENT_LEFT`,e[e.CORE_ON_SERVER_STARTED=65545]=`CORE_ON_SERVER_STARTED`,e[e.CORE_ON_SERVER_STOPPED=65546]=`CORE_ON_SERVER_STOPPED`,e[e.CORE_ON_SERVER_STOPPING=65547]=`CORE_ON_SERVER_STOPPING`,e[e.CORE_ON_CLIENT_READY=65548]=`CORE_ON_CLIENT_READY`,e[e.CORE_CLIENT_READY=65549]=`CORE_CLIENT_READY`,e[e.CORE_SERVER_INIT=65550]=`CORE_SERVER_INIT`,e[e.CORE_ON_PLUGIN_RELOADED=65551]=`CORE_ON_PLUGIN_RELOADED`,e[e.CORE_DYNAMIC_CONFIG=65555]=`CORE_DYNAMIC_CONFIG`,e[e.CORE_PROXY_RPC_AUTH_TICKET=65556]=`CORE_PROXY_RPC_AUTH_TICKET`,e[e.CORE_UPDATE_CLIENT_CONTEXT=65558]=`CORE_UPDATE_CLIENT_CONTEXT`,e[e.CORE_BACKGROUND_WORK_ACTIVE=65559]=`CORE_BACKGROUND_WORK_ACTIVE`,e[e.CORE_RESET_IDLE=65560]=`CORE_RESET_IDLE`,e[e.CORE_CLIENT_DISCONNECTING=65561]=`CORE_CLIENT_DISCONNECTING`,e[e.CORE_ON_APP_READY=65562]=`CORE_ON_APP_READY`,e[e.CORE_ON_FRONTEND_RELOADED=65563]=`CORE_ON_FRONTEND_RELOADED`,e[e.CORE_ON_USER_DATA_ERASED=65564]=`CORE_ON_USER_DATA_ERASED`,e[e.CORE_WEBRTC_OFFER=65566]=`CORE_WEBRTC_OFFER`,e[e.CORE_WEBRTC_ANSWER=65567]=`CORE_WEBRTC_ANSWER`,e[e.CORE_WEBRTC_ICE_CANDIDATE=65568]=`CORE_WEBRTC_ICE_CANDIDATE`,e[e.CORE_WEBRTC_READY=65569]=`CORE_WEBRTC_READY`,e[e.CORE_WEBRTC_AUDIO_SEGMENT=65570]=`CORE_WEBRTC_AUDIO_SEGMENT`,e[e.CORE_WEBRTC_TRACK_MAP=65571]=`CORE_WEBRTC_TRACK_MAP`,e[e.CORE_WEBRTC_VIDEO_CAPTURE=65572]=`CORE_WEBRTC_VIDEO_CAPTURE`,e[e.CORE_WEBRTC_ICE_SERVERS_REQUEST=65573]=`CORE_WEBRTC_ICE_SERVERS_REQUEST`,e[e.CORE_WEBRTC_ICE_SERVERS_RESPONSE=65574]=`CORE_WEBRTC_ICE_SERVERS_RESPONSE`,e[e.CORE_WEBRTC_CLOSE=65575]=`CORE_WEBRTC_CLOSE`,e[e.CORE_RELAY_AGENT_AUTH=65576]=`CORE_RELAY_AGENT_AUTH`,e[e.CORE_RELAY_AGENT_AUTH_RESULT=65577]=`CORE_RELAY_AGENT_AUTH_RESULT`,e[e.CORE_RELAY_HEARTBEAT=65578]=`CORE_RELAY_HEARTBEAT`,e[e.CORE_RELAY_TCP_CONNECTION_OPENED=65579]=`CORE_RELAY_TCP_CONNECTION_OPENED`,e[e.CORE_RELAY_TCP_CONNECTION_CLOSED=65580]=`CORE_RELAY_TCP_CONNECTION_CLOSED`,e[e.CORE_RELAY_TCP_DATA=65581]=`CORE_RELAY_TCP_DATA`,e[e.CORE_RELAY_UDP_DATA=65582]=`CORE_RELAY_UDP_DATA`,e[e.CORE_RELAY_ADD_TUNNEL=65583]=`CORE_RELAY_ADD_TUNNEL`,e[e.CORE_RELAY_TUNNEL_ADDED=65584]=`CORE_RELAY_TUNNEL_ADDED`,e[e.CORE_RELAY_REMOVE_TUNNEL=65585]=`CORE_RELAY_REMOVE_TUNNEL`,e[e.CORE_IKON_SERVER_ENDPOINT_HOST_INFO=65586]=`CORE_IKON_SERVER_ENDPOINT_HOST_INFO`,e[e.CORE_CLIENT_INITIALIZATION=65587]=`CORE_CLIENT_INITIALIZATION`,e[e.CORE_CLIENT_LIFECYCLE_BATCH=65588]=`CORE_CLIENT_LIFECYCLE_BATCH`,e[e.CORE_APP_CONFIG=65589]=`CORE_APP_CONFIG`,e[e.GROUP_KEEPALIVE=131072]=`GROUP_KEEPALIVE`,e[e.KEEPALIVE_REQUEST=131073]=`KEEPALIVE_REQUEST`,e[e.KEEPALIVE_RESPONSE=131074]=`KEEPALIVE_RESPONSE`,e[e.GROUP_EVENTS=262144]=`GROUP_EVENTS`,e[e.EVENTS_PROFILE_UPDATE=262145]=`EVENTS_PROFILE_UPDATE`,e[e.EVENTS_SPEECH_PLAYBACK_COMPLETE=262147]=`EVENTS_SPEECH_PLAYBACK_COMPLETE`,e[e.GROUP_ANALYTICS=524288]=`GROUP_ANALYTICS`,e[e.ANALYTICS_LOGS=524289]=`ANALYTICS_LOGS`,e[e.ANALYTICS_EVENTS=524290]=`ANALYTICS_EVENTS`,e[e.ANALYTICS_USAGES=524291]=`ANALYTICS_USAGES`,e[e.ANALYTICS_USAGE=524292]=`ANALYTICS_USAGE`,e[e.ANALYTICS_SPECIAL_LOG=524293]=`ANALYTICS_SPECIAL_LOG`,e[e.ANALYTICS_PROCESSING_UPDATE=524294]=`ANALYTICS_PROCESSING_UPDATE`,e[e.ANALYTICS_REACTIVE_PROCESSING_UPDATE=524295]=`ANALYTICS_REACTIVE_PROCESSING_UPDATE`,e[e.ANALYTICS_IKON_PROXY_SERVER_STATS=524296]=`ANALYTICS_IKON_PROXY_SERVER_STATS`,e[e.ANALYTICS_IKON_RELAY_SERVER_STATS=524297]=`ANALYTICS_IKON_RELAY_SERVER_STATS`,e[e.ANALYTICS_IKON_TURN_SERVER_STATS=524298]=`ANALYTICS_IKON_TURN_SERVER_STATS`,e[e.ANALYTICS_IKON_HOST_SERVER_STATS=524299]=`ANALYTICS_IKON_HOST_SERVER_STATS`,e[e.ANALYTICS_TRAFFIC_USAGE=524300]=`ANALYTICS_TRAFFIC_USAGE`,e[e.GROUP_ACTIONS=1048576]=`GROUP_ACTIONS`,e[e.ACTION_CALL=1048577]=`ACTION_CALL`,e[e.ACTION_ACTIVE=1048578]=`ACTION_ACTIVE`,e[e.ACTION_TEXT_OUTPUT=1048579]=`ACTION_TEXT_OUTPUT`,e[e.ACTION_TEXT_OUTPUT_DELTA=1048580]=`ACTION_TEXT_OUTPUT_DELTA`,e[e.ACTION_TEXT_OUTPUT_DELTA_FULL=1048581]=`ACTION_TEXT_OUTPUT_DELTA_FULL`,e[e.ACTION_SET_STATE=1048582]=`ACTION_SET_STATE`,e[e.ACTION_TAP=1048583]=`ACTION_TAP`,e[e.ACTION_PAN=1048584]=`ACTION_PAN`,e[e.ACTION_ZOOM=1048585]=`ACTION_ZOOM`,e[e.ACTION_OPEN_EXTERNAL_URL=1048592]=`ACTION_OPEN_EXTERNAL_URL`,e[e.ACTION_FUNCTION_REGISTER=1048600]=`ACTION_FUNCTION_REGISTER`,e[e.ACTION_FUNCTION_CALL=1048601]=`ACTION_FUNCTION_CALL`,e[e.ACTION_FUNCTION_RESULT=1048602]=`ACTION_FUNCTION_RESULT`,e[e.ACTION_GENERATE_ANSWER=1048603]=`ACTION_GENERATE_ANSWER`,e[e.ACTION_REGENERATE_ANSWER=1048604]=`ACTION_REGENERATE_ANSWER`,e[e.ACTION_CLEAR_STATE=1048606]=`ACTION_CLEAR_STATE`,e[e.ACTION_CLASSIFICATION_RESULT=1048609]=`ACTION_CLASSIFICATION_RESULT`,e[e.ACTION_AUDIO_STOP=1048610]=`ACTION_AUDIO_STOP`,e[e.ACTION_CALL_TEXT=1048611]=`ACTION_CALL_TEXT`,e[e.ACTION_CANCEL_GENERATION=1048613]=`ACTION_CANCEL_GENERATION`,e[e.ACTION_SPEECH_RECOGNIZED=1048615]=`ACTION_SPEECH_RECOGNIZED`,e[e.ACTION_CALL_RESULT=1048616]=`ACTION_CALL_RESULT`,e[e.ACTION_DOWNLOAD=1048618]=`ACTION_DOWNLOAD`,e[e.ACTION_PLAY_SOUND=1048621]=`ACTION_PLAY_SOUND`,e[e.ACTION_STOP_SOUND=1048623]=`ACTION_STOP_SOUND`,e[e.ACTION_START_RECORDING=1048624]=`ACTION_START_RECORDING`,e[e.ACTION_STOP_RECORDING=1048625]=`ACTION_STOP_RECORDING`,e[e.ACTION_FUNCTION_ENUMERATION_ITEM=1048627]=`ACTION_FUNCTION_ENUMERATION_ITEM`,e[e.ACTION_FUNCTION_ENUMERATION_END=1048628]=`ACTION_FUNCTION_ENUMERATION_END`,e[e.ACTION_FUNCTION_CANCEL=1048629]=`ACTION_FUNCTION_CANCEL`,e[e.ACTION_FUNCTION_DISPOSE=1048630]=`ACTION_FUNCTION_DISPOSE`,e[e.ACTION_FUNCTION_ERROR=1048631]=`ACTION_FUNCTION_ERROR`,e[e.ACTION_FUNCTION_ACK=1048632]=`ACTION_FUNCTION_ACK`,e[e.ACTION_FUNCTION_AWAITING_APPROVAL=1048633]=`ACTION_FUNCTION_AWAITING_APPROVAL`,e[e.ACTION_FUNCTION_APPROVAL_REQUIRED=1048634]=`ACTION_FUNCTION_APPROVAL_REQUIRED`,e[e.ACTION_FUNCTION_APPROVAL_RESPONSE=1048635]=`ACTION_FUNCTION_APPROVAL_RESPONSE`,e[e.UI_UPDATE_ACK=1048636]=`UI_UPDATE_ACK`,e[e.ACTION_CALL2=1048637]=`ACTION_CALL2`,e[e.ACTION_FUNCTION_REGISTER_BATCH=1048638]=`ACTION_FUNCTION_REGISTER_BATCH`,e[e.ACTION_CUSTOM_USER_MESSAGE=1048641]=`ACTION_CUSTOM_USER_MESSAGE`,e[e.ACTION_URL_CHANGED=1048642]=`ACTION_URL_CHANGED`,e[e.ACTION_FILE_UPLOAD_PRE_START2=1048643]=`ACTION_FILE_UPLOAD_PRE_START2`,e[e.ACTION_FILE_UPLOAD_PRE_START_RESPONSE2=1048644]=`ACTION_FILE_UPLOAD_PRE_START_RESPONSE2`,e[e.ACTION_FILE_UPLOAD_START2=1048645]=`ACTION_FILE_UPLOAD_START2`,e[e.ACTION_FILE_UPLOAD_START_RESPONSE2=1048646]=`ACTION_FILE_UPLOAD_START_RESPONSE2`,e[e.ACTION_FILE_UPLOAD_DATA2=1048647]=`ACTION_FILE_UPLOAD_DATA2`,e[e.ACTION_FILE_UPLOAD_ACK2=1048648]=`ACTION_FILE_UPLOAD_ACK2`,e[e.ACTION_FILE_UPLOAD_END2=1048649]=`ACTION_FILE_UPLOAD_END2`,e[e.ACTION_FILE_UPLOAD_COMPLETE2=1048650]=`ACTION_FILE_UPLOAD_COMPLETE2`,e[e.ACTION_FUNCTION_ENUMERATION_ITEM_BATCH=1048651]=`ACTION_FUNCTION_ENUMERATION_ITEM_BATCH`,e[e.ACTION_CALL_ACK=1048652]=`ACTION_CALL_ACK`,e[e.ACTION_TRIGGER_CRON=1048653]=`ACTION_TRIGGER_CRON`,e[e.ACTION_RESULT=1048654]=`ACTION_RESULT`,e[e.UI_RESYNC_REQUEST=1048655]=`UI_RESYNC_REQUEST`,e[e.ACTION_USER_DATA_ERASURE=1048656]=`ACTION_USER_DATA_ERASURE`,e[e.ACTION_FILE_UPLOAD_RESUME2=1048657]=`ACTION_FILE_UPLOAD_RESUME2`,e[e.ACTION_FILE_UPLOAD_RESUME_RESPONSE2=1048658]=`ACTION_FILE_UPLOAD_RESUME_RESPONSE2`,e[e.GROUP_UI=2097152]=`GROUP_UI`,e[e.UI_STREAM_BEGIN=2097153]=`UI_STREAM_BEGIN`,e[e.UI_STREAM_END=2097154]=`UI_STREAM_END`,e[e.UI_STYLES=2097188]=`UI_STYLES`,e[e.UI_UPDATE=2097190]=`UI_UPDATE`,e[e.UI_STYLES_BATCH=2097192]=`UI_STYLES_BATCH`,e[e.UI_STYLES_DELETE=2097193]=`UI_STYLES_DELETE`,e[e.GROUP_COMMON=4128768]=`GROUP_COMMON`,e[e.GROUP_AUDIO=4194304]=`GROUP_AUDIO`,e[e.AUDIO_STREAM_BEGIN=4194305]=`AUDIO_STREAM_BEGIN`,e[e.AUDIO_STREAM_END=4194306]=`AUDIO_STREAM_END`,e[e.AUDIO_FRAME_VOLUME=4194308]=`AUDIO_FRAME_VOLUME`,e[e.AUDIO_FRAME=4194309]=`AUDIO_FRAME`,e[e.AUDIO_SHAPE_FRAME=4194310]=`AUDIO_SHAPE_FRAME`,e[e.AUDIO_PLAYBACK_REPORT=4194311]=`AUDIO_PLAYBACK_REPORT`,e[e.GROUP_VIDEO=8388608]=`GROUP_VIDEO`,e[e.VIDEO_STREAM_BEGIN=8388609]=`VIDEO_STREAM_BEGIN`,e[e.VIDEO_STREAM_END=8388610]=`VIDEO_STREAM_END`,e[e.VIDEO_FRAME=8388611]=`VIDEO_FRAME`,e[e.VIDEO_REQUEST_IDR_FRAME=8388612]=`VIDEO_REQUEST_IDR_FRAME`,e[e.VIDEO_INVALIDATE_FRAME=8388613]=`VIDEO_INVALIDATE_FRAME`,e[e.GROUP_ALL=16711680]=`GROUP_ALL`,e[e.GROUP_APP_LOCAL=1073741824]=`GROUP_APP_LOCAL`,e[e.CONSTANT_GROUP_MASK=2147418112]=`CONSTANT_GROUP_MASK`,e}({});function y(e){let t={};return e&&Object.assign(t,e),t}function te(e){return new s(1).finish()}function b(e,t,n){return i(131074,te(e),1,t,n)}var x=class extends Error{cause;constructor(e,t){super(e),this.cause=t,this.name=`ConnectionError`}},S=class extends x{constructor(e,t){super(e,t),this.name=`TransportError`}},C=class extends S{constructor(e){super(`No keepalive received within ${e}ms`),this.name=`KeepaliveTimeoutError`}},w=class extends S{constructor(e,t){super(e,t),this.name=`AuthRejectedError`}},T=class extends x{constructor(e){super(`Maximum reconnection attempts (${e}) exceeded`),this.name=`MaxRetriesExceededError`}};function ne(e,t){return new Promise((n,r)=>{let i=()=>{clearTimeout(a),r(new DOMException(`Aborted`,`AbortError`))},a=setTimeout(()=>{t?.removeEventListener(`abort`,i),n()},e);if(t?.aborted){clearTimeout(a),r(new DOMException(`Aborted`,`AbortError`));return}t?.addEventListener(`abort`,i,{once:!0})})}let E=1;const re=new Map;function ie(e){E=e}const D={0:`DEBUG`,1:`INFO`,2:`WARN`,3:`ERROR`,4:`NONE`};function ae(e,t){return`[${e}] ${t}`}function O(e,t,n,r){let i={timestamp:new Date().toISOString(),level:e,levelName:D[e],component:t,message:n,args:r};for(let[t,n]of re)if(e>=(n?.minLevel??2))try{t(i)}catch{}if(E<=e){let i=ae(t,n);switch(e){case 0:console.debug(i,...r);break;case 1:console.info(i,...r);break;case 2:console.warn(i,...r);break;case 3:console.error(i,...r)}}}function k(e){return{debug(t,...n){O(0,e,t,n)},info(t,...n){O(1,e,t,n)},warn(t,...n){O(2,e,t,n)},error(t,...n){O(3,e,t,n)}}}function oe(e,t){if(typeof window>`u`)return null;let n=new URLSearchParams(window.location.search),r=n.get(e);if(r!==null)return r;let i=n.get(e.replace(/-/g,`_`));return i===null?t?n.get(t):null:i}function se(e,t){let n=oe(e,t);return n===`true`||n!==`false`&&null}function ce(){return se(`ikon-retry`)!==!1}const A=k(`WebSocketTransport`);var j=class{ws=null;keepaliveTimeout=null;isClosed=!1;keepaliveResponseMessage=null;firstMessageResolver=null;keepaliveTimeoutMs;connectionTimeoutMs;callbacks;sessionId;constructor(e){this.callbacks=e.callbacks,this.sessionId=e.sessionId,this.keepaliveTimeoutMs=e.keepaliveTimeoutMs,this.connectionTimeoutMs=e.connectionTimeoutMs??1e4}get isConnected(){return this.ws?.readyState===WebSocket.OPEN}async connect(e,t){this.isClosed=!1;let n=Date.now();return new Promise((r,i)=>{try{this.ws=new WebSocket(e),this.ws.binaryType=`arraybuffer`}catch(e){i(new S(`Failed to create WebSocket: ${e}`,e instanceof Error?e:void 0));return}let a=!1,o=!1,s=()=>{clearTimeout(u),this.ws&&(this.ws.onopen=null,this.ws.onerror=null,this.ws.onclose=null,this.ws.onmessage=null)},c=()=>{o||(o=!0,clearTimeout(u),this.firstMessageResolver=null,A.debug(`WebSocket connected in ${Date.now()-n}ms`),r())},l=e=>{o||(o=!0,this.firstMessageResolver=null,s(),i(e))};this.firstMessageResolver=c;let u=setTimeout(()=>{this.ws?.close(),A.warn(`WebSocket connection timeout after ${this.connectionTimeoutMs}ms`),l(new S(`WebSocket connection timeout`))},this.connectionTimeoutMs);this.ws.onopen=()=>{a=!0,this.ws.send(t),this.resetKeepaliveTimeout()},this.ws.onerror=()=>{A.debug(`WebSocket connection failed after ${Date.now()-n}ms`),l(new S(`WebSocket connection failed`))},this.ws.onclose=e=>{if(this.clearKeepaliveTimeout(),!o){l(a?new w(`WebSocket closed before first server message`):new S(`WebSocket connection closed before opening`));return}if(this.isClosed)return;let t=e.wasClean&&(e.code===1e3||e.code===1001),n=e.reason||`code=${e.code}`;this.callbacks.onClose(n,t)},this.ws.onmessage=e=>{this.handleProtocolMessage(new Uint8Array(e.data))}})}send(e){this.ws?.readyState===WebSocket.OPEN?this.ws.send(e):A.warn(`Cannot send: WebSocket not connected`)}close(){this.isClosed=!0,this.clearKeepaliveTimeout(),this.ws&&=(this.ws.close(1e3,`Client closing`),null)}getKeepaliveResponse(){return this.keepaliveResponseMessage||=b(y(),this.sessionId),this.keepaliveResponseMessage}handleProtocolMessage(e){try{let t=r(e).opcode;if(this.firstMessageResolver&&this.firstMessageResolver(),t===v.KEEPALIVE_REQUEST){this.send(this.getKeepaliveResponse()),this.resetKeepaliveTimeout();return}this.resetKeepaliveTimeout(),this.callbacks.onProtocolMessage(e)}catch(e){A.error(`Failed to process protocol message:`,e),this.callbacks.onError(e instanceof Error?e:Error(String(e)))}}resetKeepaliveTimeout(){this.clearKeepaliveTimeout(),!(this.keepaliveTimeoutMs<=0)&&(this.keepaliveTimeout=setTimeout(()=>{A.error(`No keepalive received in ${this.keepaliveTimeoutMs}ms, closing connection`),this.callbacks.onError(new C(this.keepaliveTimeoutMs)),this.close()},this.keepaliveTimeoutMs))}clearKeepaliveTimeout(){this.keepaliveTimeout&&=(clearTimeout(this.keepaliveTimeout),null)}};const M=k(`WebTransportTransport`);function N(){return typeof WebTransport<`u`}var le=class{transport=null;stream=null;reader=null;writer=null;keepaliveTimeout=null;readLoopActive=!1;isClosed=!1;receiveBuffer=new Uint8Array(65536);receiveBufferOffset=0;receiveBufferLength=0;receiveDataView=null;receiveDataViewBuffer=null;keepaliveResponseMessage=null;firstMessageResolver=null;firstMessageRejecter=null;keepaliveTimeoutMs;connectionTimeoutMs;callbacks;sessionId;constructor(e){this.callbacks=e.callbacks,this.sessionId=e.sessionId,this.keepaliveTimeoutMs=e.keepaliveTimeoutMs,this.connectionTimeoutMs=e.connectionTimeoutMs??1e4}get isConnected(){return this.transport!==null&&this.writer!==null}async connect(e,t){if(!N())throw new S(`WebTransport is not supported in this browser`);this.isClosed=!1;let n=Date.now(),r=new Promise((e,t)=>{this.firstMessageResolver=e,this.firstMessageRejecter=t});try{this.transport=new WebTransport(e);let i,a=new Promise((e,t)=>{i=setTimeout(()=>t(new S(`WebTransport connection timeout`)),this.connectionTimeoutMs)});try{await Promise.race([this.transport.ready,a])}catch(e){throw e instanceof S&&M.warn(`WebTransport connection timeout after ${this.connectionTimeoutMs}ms`),e}finally{clearTimeout(i)}this.transport.closed.then(()=>{this.handleClose(`Connection closed`,!0)}).catch(e=>{M.error(`WebTransport connection closed with error:`,e),this.handleClose(e instanceof Error?e.message:`Connection error`,!1)}),this.stream=await this.transport.createBidirectionalStream(),this.reader=this.stream.readable.getReader(),this.writer=this.stream.writable.getWriter(),await this.writer.write(t),this.resetKeepaliveTimeout(),this.startReadLoop();let o=Math.max(this.connectionTimeoutMs-(Date.now()-n),1),s,c=new Promise((e,t)=>{s=setTimeout(()=>t(new S(`WebTransport closed before first server message`)),o)});try{await Promise.race([r,c])}finally{clearTimeout(s)}this.firstMessageResolver=null,this.firstMessageRejecter=null,M.info(`WebTransport connected in ${Date.now()-n}ms`)}catch(e){this.firstMessageResolver=null,this.firstMessageRejecter=null,this.isClosed=!0,this.cleanup();let t=Date.now()-n;throw M.warn(`WebTransport connection failed after ${t}ms: ${e}`),new S(`Failed to connect WebTransport: ${e}`,e instanceof Error?e:void 0)}}send(e){if(!this.writer){M.warn(`Cannot send: WebTransport not connected`);return}this.writer.write(e).catch(e=>{M.error(`Failed to send protocol message:`,e),this.callbacks.onError(e instanceof Error?e:Error(String(e)))})}close(){this.isClosed=!0,this.clearKeepaliveTimeout(),this.readLoopActive=!1,this.cleanup()}async startReadLoop(){if(this.reader){this.readLoopActive=!0;try{for(;this.readLoopActive&&this.reader;){let{value:e,done:t}=await this.reader.read();if(t)break;e&&(this.appendToBuffer(e),this.processBufferedMessages())}this.readLoopActive&&this.handleClose(`Stream ended`,!1)}catch(e){this.readLoopActive&&(M.error(`Read loop error:`,e),this.callbacks.onError(e instanceof Error?e:Error(String(e))))}}}appendToBuffer(e){let t=this.receiveBufferLength+e.length,n=this.receiveBufferOffset+this.receiveBufferLength;if(n+e.length>this.receiveBuffer.length)if(t>this.receiveBuffer.length){let e=Math.max(t,this.receiveBuffer.length*2),r=new Uint8Array(e);r.set(this.receiveBuffer.subarray(this.receiveBufferOffset,n)),this.receiveBuffer=r,this.receiveBufferOffset=0,this.receiveDataViewBuffer=null}else this.receiveBuffer.copyWithin(0,this.receiveBufferOffset,n),this.receiveBufferOffset=0;this.receiveBuffer.set(e,this.receiveBufferOffset+this.receiveBufferLength),this.receiveBufferLength+=e.length}getReceiveDataView(){let e=this.receiveBuffer.buffer;return this.receiveDataViewBuffer!==e&&(this.receiveDataViewBuffer=e,this.receiveDataView=new DataView(e)),this.receiveDataView}getKeepaliveResponse(){return this.keepaliveResponseMessage||=b(y(),this.sessionId),this.keepaliveResponseMessage}processBufferedMessages(){let e=this.getReceiveDataView();for(;this.receiveBufferLength>=4;){let t=e.getUint32(this.receiveBufferOffset,!0);if(t<4){M.error(`Invalid message length: ${t}`),this.callbacks.onError(Error(`Invalid protocol message length: ${t}`)),this.receiveBufferOffset=0,this.receiveBufferLength=0;return}if(this.receiveBufferLength<t)return;let n=this.receiveBuffer.subarray(this.receiveBufferOffset,this.receiveBufferOffset+t);this.receiveBufferOffset+=t,this.receiveBufferLength-=t,this.handleProtocolMessage(n)}this.receiveBufferLength===0&&(this.receiveBufferOffset=0)}handleProtocolMessage(e){try{let t=r(e).opcode;if(this.firstMessageResolver&&this.firstMessageResolver(),t===v.KEEPALIVE_REQUEST){this.send(this.getKeepaliveResponse()),this.resetKeepaliveTimeout();return}this.resetKeepaliveTimeout(),this.callbacks.onProtocolMessage(e)}catch(e){M.error(`Failed to process protocol message:`,e),this.callbacks.onError(e instanceof Error?e:Error(String(e)))}}handleClose(e,t){if(!this.isClosed){if(this.isClosed=!0,this.clearKeepaliveTimeout(),this.readLoopActive=!1,this.cleanup(),this.firstMessageRejecter){this.firstMessageRejecter(new w(`WebTransport closed before first server message: ${e}`)),this.firstMessageResolver=null,this.firstMessageRejecter=null;return}this.callbacks.onClose(e,t)}}resetKeepaliveTimeout(){this.clearKeepaliveTimeout(),!(this.keepaliveTimeoutMs<=0)&&(this.keepaliveTimeout=setTimeout(()=>{M.error(`No keepalive received in ${this.keepaliveTimeoutMs}ms, closing connection`),this.callbacks.onError(new C(this.keepaliveTimeoutMs)),this.close()},this.keepaliveTimeoutMs))}clearKeepaliveTimeout(){this.keepaliveTimeout&&=(clearTimeout(this.keepaliveTimeout),null)}cleanup(){if(this.reader&&=(this.reader.releaseLock(),null),this.writer&&=(this.writer.releaseLock(),null),this.stream=null,this.receiveBufferOffset=0,this.receiveBufferLength=0,this.transport){try{this.transport.close()}catch{}this.transport=null}}};const P=k(`Channel`);var F=class{state=`disconnected`;transport=null;config;entrypoint;constructor(e){this.config=e,this.entrypoint=e.entrypoint}get channelState(){return this.state}get opcodeGroups(){return this.entrypoint.OpcodeGroupsFromServer}get type(){return this.entrypoint.Type}get isConnected(){return this.transport?.isConnected??!1}async connect(){if(this.state!==`disconnected`)throw Error(`Cannot connect: already in state ${this.state}`);this.setState(`connecting`);try{await this.connectTransport(),this.setState(`connected`)}catch(e){throw this.setState(`disconnected`),e}}disconnect(){this.transport&&=(this.transport.close(),null),this.setState(`disconnected`)}triggerReconnect(e){this.transport&&=(this.transport.close(),null),this.config.onClose?.(e,!1)}checkHealth(){this.state===`connected`&&this.transport&&!this.transport.isConnected&&this.handleClose(`Transport dead after tab resume`,!1)}send(e){if(!this.transport?.isConnected){P.warn(`Cannot send: channel not connected`);return}this.transport.send(e)}async connectTransport(){let e=this.entrypoint,t={sessionId:this.config.sessionId,keepaliveTimeoutMs:this.config.keepaliveTimeoutMs,connectionTimeoutMs:this.config.connectionTimeoutMs,callbacks:{onProtocolMessage:e=>this.handleProtocolMessage(e),onClose:(e,t)=>this.handleClose(e,t),onError:e=>this.handleError(e)}};switch(e.Type){case _.WebSocket:case _.WebSocketProxy:this.transport=new j(t);break;case _.WebTransport:case _.WebTransportProxy:if(!N())throw Error(`WebTransport is not supported in this browser`);this.transport=new le(t);break;default:throw Error(`Unsupported entrypoint type: ${_[e.Type]}`)}await this.transport.connect(e.Uri,e.AuthTicket)}handleProtocolMessage(n){try{let r=e(n);if(t(r)===v.CORE_ON_SERVER_STOPPING){P.debug(`Received server stopping message`),this.setState(`stopped`),this.transport?.close();return}this.config.onProtocolMessage?.(r)}catch(e){P.error(`Failed to handle protocol message:`,e),this.config.onError?.(e instanceof Error?e:Error(String(e)))}}handleClose(e,t){this.transport=null,this.config.onClose?.(e,t)}handleError(e){this.config.onError?.(e),e instanceof C&&this.handleClose(`Keepalive timeout`,!1)}setState(e){this.state!==e&&(this.state=e,this.config.onStateChange?.(e))}};const I=k(`ChannelManager`);var ue=class{channels=new Map;activeType=null;state=`idle`;reconnectAttempts=0;shouldReconnect=!0;entrypoints=[];abortController=null;connectionTimeoutMs;stabilityTimer=null;config;constructor(e){this.config=e}get managerState(){return this.state}get activeEndpointType(){return this.activeType}async connect(e,t){if(this.state!==`idle`&&this.state!==`offline`)throw Error(`Cannot connect: already in state ${this.state}`);if(this.entrypoints=e,this.shouldReconnect=!0,this.reconnectAttempts=0,this.abortController=new AbortController,t?.retry){this.attemptReconnect();return}await this.connectInternal()}disconnect(){this.shouldReconnect=!1,this.abortController?.abort(),this.abortController=null,this.disconnectAll(),this.setState(`idle`)}sendProtocolMessage(e){let t=n(e);for(let[n,r]of this.channels)if(n&t){r.send(e);return}this.state===`connected`&&I.warn(`No channel found for message`)}sendToAll(e){for(let t of this.channels.values())t.send(e)}checkHealth(){if(this.state===`connected`)for(let e of this.channels.values())e.checkHealth()}triggerReconnect(e){if(this.state===`connected`){I.debug(`Forcing reconnect: ${e}`);for(let t of this.channels.values())t.triggerReconnect(e)}}async connectInternal(e=!1){this.setState(`connecting`);let t=this.entrypoints.filter(e=>e.Type!==_.WebRTC),n=this.groupByType(t);if(n.size===0)throw this.setState(`offline`),Error(`No entrypoints available`);let r;if(this.config.orderedEndpointTypes&&this.config.orderedEndpointTypes.length>0){let e=new Set(n.keys());r=this.config.orderedEndpointTypes.filter(t=>e.has(t))}else r=this.config.endpointSelector?this.config.endpointSelector.getOrderedTypes(n):Array.from(n.keys());this.connectionTimeoutMs=r.length>1?5e3:1e4,I.debug(`Endpoint types to try: [${r.map(e=>_[e]).join(`, `)}], transport timeout: ${this.connectionTimeoutMs}ms`);for(let e of r){if(!this.shouldReconnect)return;let t=n.get(e),r=Date.now();I.debug(`Trying ${_[e]} (${t.length} channel(s))`);try{await this.connectAllChannels(t),this.config.endpointSelector?.rememberWorkingType(e),this.config.onRememberWorkingType?.(e),this.activeType=e,I.debug(`Connected via ${_[e]} in ${Date.now()-r}ms`),this.setState(`connected`),this.startStabilityTimer();return}catch(t){I.warn(`Failed to connect using ${_[e]} after ${Date.now()-r}ms: ${t instanceof Error?t.message:t}`);let i=this.channels.size>0;if(this.disconnectAll(),t instanceof w)throw t;if(i&&this.config.onRefreshEntrypoints)try{I.info(`Partial connection detected, refreshing entrypoints`);let e=await this.config.onRefreshEntrypoints();this.entrypoints=e.entrypoints,this.config.sessionId=e.sessionId;let t=e.entrypoints.filter(e=>e.Type!==_.WebRTC),r=this.groupByType(t);for(let[e,t]of r)n.set(e,t)}catch(e){I.warn(`Failed to refresh entrypoints: ${e}`)}}}throw e||this.setState(`offline`),Error(`Failed to connect using any endpoint type`)}async connectAllChannels(e){if(e.length===0)throw Error(`No entrypoints to connect`);let t=(await Promise.allSettled(e.map(e=>this.connectChannel(e)))).filter(e=>e.status===`rejected`);if(t.length>0){let e=t.map(e=>e.reason instanceof Error?e.reason.message:String(e.reason));throw t.some(e=>e.reason instanceof w)?new w(e.join(`, `)):Error(e.join(`, `))}}async connectChannel(e){let t=new F({entrypoint:e,sessionId:this.config.sessionId,keepaliveTimeoutMs:this.config.keepaliveTimeoutMs,connectionTimeoutMs:this.connectionTimeoutMs,onProtocolMessage:e=>{this.config.onProtocolMessage?.(e)},onStateChange:t=>{this.handleChannelStateChange(e.OpcodeGroupsFromServer,t)},onClose:(t,n)=>{this.handleChannelClose(e.OpcodeGroupsFromServer,t,n)},onError:e=>{this.config.onError?.(e)}});await t.connect(),this.channels.set(e.OpcodeGroupsFromServer,t)}groupByType(e){let t=new Map;for(let n of e){let e=t.get(n.Type)??[];e.push(n),t.set(n.Type,e)}return t}handleChannelStateChange(e,t){t===`stopped`&&(this.shouldReconnect=!1,this.disconnectAll(),this.setState(`stopped`))}handleChannelClose(e,t,n){this.state!==`idle`&&this.state!==`stopped`&&this.state!==`offline`&&this.channels.has(e)&&this.state===`connected`&&(I.warn(`Channel closed unexpectedly, attempting reconnect`),this.disconnectAll(),this.attemptReconnect())}async attemptReconnect(){if(this.shouldReconnect){if(!ce()){I.warn(`Retry disabled via ikon-retry=false, skipping reconnect`),this.setState(`offline`),this.config.onError?.(new T(0));return}if(this.reconnectAttempts>=this.config.maxReconnectAttempts){I.warn(`Max reconnect attempts (${this.config.maxReconnectAttempts}) reached`),this.setState(`offline`),this.config.onError?.(new T(this.config.maxReconnectAttempts));return}if(this.setState(`reconnecting`),this.reconnectAttempts++,this.reconnectAttempts>1){I.info(`Reconnecting in ${this.config.reconnectBackoffMs}ms (attempt ${this.reconnectAttempts}/${this.config.maxReconnectAttempts})`);try{await ne(this.config.reconnectBackoffMs,this.abortController?.signal)}catch{return}}else I.info(`Reconnecting immediately (attempt ${this.reconnectAttempts}/${this.config.maxReconnectAttempts})`);if(this.shouldReconnect)try{await this.connectInternal(!0)}catch(e){if(e instanceof w){I.warn(`Auth rejected during reconnect, stopping retries and signaling full re-auth`),this.config.onError?.(e),this.setState(`offline`);return}await this.attemptReconnect()}}}disconnectAll(){for(let e of this.channels.values())e.disconnect();this.channels.clear(),this.activeType=null}setState(e){this.state!==e&&(this.state===`connected`&&e!==`connected`&&this.clearStabilityTimer(),this.state=e,this.config.onStateChange?.(e))}startStabilityTimer(){this.clearStabilityTimer(),this.stabilityTimer=setTimeout(()=>{this.stabilityTimer=null,this.state===`connected`&&(this.reconnectAttempts=0)},5e3)}clearStabilityTimer(){this.stabilityTimer&&=(clearTimeout(this.stabilityTimer),null)}};const L=k(`ProtocolWorker`),R=(e,t)=>{self.postMessage(e,t??[])};let z=null,B=null,V=null,H,U=null;const W=[],G=[],K=new Map,q=[],J=[],Y=new Map,X=[];function Z(){try{z?.disconnect()}catch(e){L.warn(`Failed to disconnect channel manager: ${e}`)}z=null;for(let e=0;e<G.length;e++)try{G[e].port.close()}catch{}W.length=0,G.length=0,K.clear();for(let e=0;e<J.length;e++)try{J[e].port.close()}catch{}q.length=0,J.length=0,Y.clear()}function Q(e){let t=e instanceof Error?e:Error(String(e));R({type:`error`,error:{name:t.name,message:t.message,stack:t.stack}})}function de(){let e=0;for(let t=0;t<G.length;t++)e|=G[t].opcodeGroupsMask;return e}function fe(e){if(H===void 0)return!0;let t=n(e);return(t&H)!==0||(t&de())!==0}function $(e){X.length=0;for(let t=0;t<G.length;t++){let n=G[t];(n.opcodeGroupsMask&e)!==0&&X.push(n.port)}return X}function pe(e,t){return(n(e)&t)!==0}function me(t,n){if(!z||!n||typeof n!=`object`)return;let r=n;if(!(r.type!==`send`||!(r.message instanceof ArrayBuffer)))try{let n=e(new Uint8Array(r.message));if(!pe(n,t))return;z.sendProtocolMessage(n),U&&U.postMessage({direction:`sent`,message:Array.from(n)})}catch(e){Q(e)}}async function he(e){Z(),z=new ue({sessionId:e.sessionId,keepaliveTimeoutMs:e.keepaliveTimeoutMs,reconnectBackoffMs:e.reconnectBackoffMs,maxReconnectAttempts:e.maxReconnectAttempts,orderedEndpointTypes:e.orderedEndpointTypes,webRtcEnabled:e.webRtcEnabled,onStateChange:e=>{R({type:`state`,state:e,activeType:z?.activeEndpointType??void 0})},onRememberWorkingType:()=>{R({type:`state`,state:z?.managerState??`idle`,activeType:z?.activeEndpointType??void 0})},onError:e=>{Q(e)},onRefreshEntrypoints:()=>new Promise((e,t)=>{B=e,V=t,R({type:`refreshEntrypoints`})}),onProtocolMessage:e=>{U&&(U.postMessage({direction:`received`,message:Array.from(e)}),t(e)===v.ANALYTICS_LOGS&&U.postMessage({type:`serverLogs`,message:Array.from(e)}));let i=n(e),a=fe(e),o=$(i);if(!(!a&&o.length===0))try{let t=r(e),n=e.buffer instanceof ArrayBuffer&&e.byteOffset===0&&e.byteLength===e.buffer.byteLength,i=o.length>0;if(i&&!a&&o.length===1&&n){let n=e.buffer;o[0].postMessage({type:`protocol`,message:n,headers:t},[n]);return}if(!i&&a&&n){let n=e.buffer;R({type:`protocol`,message:n,headers:t},[n]);return}if(i&&n){let n=[];for(let t=1;t<o.length;t++)n.push(e.slice().buffer);let r=a?e.slice().buffer:null,i=e.buffer;o[0].postMessage({type:`protocol`,message:i,headers:t},[i]);for(let e=1;e<o.length;e++)o[e].postMessage({type:`protocol`,message:n[e-1],headers:t},[n[e-1]]);r&&R({type:`protocol`,message:r,headers:t},[r]);return}if(i)for(let n of o){let r=e.slice().buffer;n.postMessage({type:`protocol`,message:r,headers:t},[r])}if(a){let n=e.slice().buffer;R({type:`protocol`,message:n,headers:t},[n])}}catch(e){Q(e)}}}),await z.connect(e.entrypoints,{retry:e.retry})}self.addEventListener(`message`,t=>{let i=t.data;if(i.type===`connect`){he(i).catch(e=>{L.error(`Failed to connect: ${e}`),Q(e),Z()});return}if(i.type===`disconnect`){Z(),R({type:`state`,state:`idle`});return}if(i.type===`send`){if(!z)return;try{let t=e(new Uint8Array(i.message));z.sendProtocolMessage(t),U&&U.postMessage({direction:`sent`,message:Array.from(t)})}catch(e){Q(e)}return}if(i.type===`setInterest`){H=i.opcodeGroupsMask;return}if(i.type===`enableDevtools`){i.enabled&&!U?U=new BroadcastChannel(`ikon:devtools`):!i.enabled&&U&&(U.close(),U=null);return}if(i.type===`setLogLevel`){ie(i.level);return}if(i.type===`checkHealth`){z?.checkHealth();return}if(i.type===`triggerReconnect`){z?.triggerReconnect(i.reason);return}if(i.type===`refreshedEntrypoints`){B&&(B({entrypoints:i.entrypoints,sessionId:i.sessionId}),B=null,V=null);return}if(i.type===`refreshEntrypointsFailed`){V&&=(V(Error(`Failed to refresh entrypoints`)),B=null,null);return}if(i.type===`forwardToPorts`){try{let t=e(new Uint8Array(i.message)),a=$(n(t));if(a.length>0){let e=r(t);for(let n of a){let r=t.slice().buffer;n.postMessage({type:`protocol`,message:r,headers:e},[r])}}}catch(e){Q(e)}return}if(i.type===`attachPort`){try{i.port.start?.()}catch{}let e=W.length;W.push(i.portId),G.push({port:i.port,opcodeGroupsMask:i.opcodeGroupsMask}),K.set(i.portId,e);return}if(i.type===`detachPort`){let e=K.get(i.portId);if(e!==void 0){let t=G[e];try{t.port.close()}catch{}let n=W.length-1;if(e!==n){let t=W[n];W[e]=t,G[e]=G[n],K.set(t,e)}W.length--,G.length--,K.delete(i.portId)}return}if(i.type===`attachSendPort`){let e=Y.get(i.portId);if(e!==void 0){let t=J[e];try{t.port.close()}catch{}let n=q.length-1;if(e!==n){let t=q[n];q[e]=t,J[e]=J[n],Y.set(t,e)}q.length--,J.length--,Y.delete(i.portId)}let t={port:i.port,opcodeGroupsMask:i.opcodeGroupsMask},n=q.length;q.push(i.portId),J.push(t),Y.set(i.portId,n);try{t.port.start?.()}catch{}t.port.addEventListener(`message`,e=>{me(t.opcodeGroupsMask,e.data)});return}if(i.type===`detachSendPort`){let e=Y.get(i.portId);if(e!==void 0){let t=J[e];try{t.port.close()}catch{}let n=q.length-1;if(e!==n){let t=q[n];q[e]=t,J[e]=J[n],Y.set(t,e)}q.length--,J.length--,Y.delete(i.portId)}return}});
|