openrtc 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/README.md +1 -2
  2. package/dist/{core/types.d.ts → DelegatingRuntimeAdapter-CW8d78dZ.d.ts} +275 -95
  3. package/dist/IpcRuntimeAdapter-CT-W0Mtp.d.ts +24 -0
  4. package/dist/auth/index.d.ts +75 -1
  5. package/dist/auth/index.js +1 -1
  6. package/dist/auth/internal.d.ts +3 -1
  7. package/dist/auth/internal.js +1 -1
  8. package/dist/chunk-4MH42GUI.js +2 -0
  9. package/dist/chunk-CQAKCS2S.js +4 -0
  10. package/dist/chunk-D54VGRRH.js +1 -0
  11. package/dist/chunk-DIQYFAGL.js +2 -0
  12. package/dist/chunk-PZ25OCVG.js +2 -0
  13. package/dist/chunk-UVASANPG.js +1 -0
  14. package/dist/factories-0TxDPMeu.d.ts +1041 -0
  15. package/dist/index.d.ts +160 -3
  16. package/dist/index.js +1 -3
  17. package/dist/openrtc_bg.wasm +0 -0
  18. package/dist/runtime/WasmRuntimeAdapter.d.ts +5 -3
  19. package/dist/runtime/WasmRuntimeAdapter.js +1 -11
  20. package/dist/runtime/index.d.ts +796 -6
  21. package/dist/runtime/index.js +1 -5
  22. package/dist/runtime/tauri.d.ts +12 -8
  23. package/dist/runtime/tauri.js +1 -22
  24. package/package.json +11 -7
  25. package/wasm/openrtc.d.ts +61 -25
  26. package/wasm/openrtc.js +417 -259
  27. package/wasm/openrtc_bg.wasm +0 -0
  28. package/wasm/openrtc_bg.wasm.d.ts +27 -24
  29. package/wasm/package.json +1 -1
  30. package/dist/OpenRTC.d.ts +0 -71
  31. package/dist/OpenRTC.js +0 -130
  32. package/dist/api/MediaTransport.d.ts +0 -7
  33. package/dist/api/MediaTransport.js +0 -262
  34. package/dist/api/PlutoPeerConnection.d.ts +0 -50
  35. package/dist/api/PlutoPeerConnection.js +0 -434
  36. package/dist/api/PlutoWebSocket.d.ts +0 -24
  37. package/dist/api/PlutoWebSocket.js +0 -113
  38. package/dist/api/PlutoWebTransport.d.ts +0 -29
  39. package/dist/api/PlutoWebTransport.js +0 -105
  40. package/dist/auth/host.d.ts +0 -73
  41. package/dist/auth/host.js +0 -513
  42. package/dist/compat/index.d.ts +0 -20
  43. package/dist/compat/index.js +0 -20
  44. package/dist/core/Client.d.ts +0 -352
  45. package/dist/core/Client.js +0 -3689
  46. package/dist/core/Connection.d.ts +0 -67
  47. package/dist/core/Connection.js +0 -404
  48. package/dist/core/IEngineBridge.d.ts +0 -18
  49. package/dist/core/IEngineBridge.js +0 -1
  50. package/dist/core/ISignalingTransport.d.ts +0 -13
  51. package/dist/core/ISignalingTransport.js +0 -1
  52. package/dist/core/PeerLifecycleManager.d.ts +0 -43
  53. package/dist/core/PeerLifecycleManager.js +0 -330
  54. package/dist/core/PeerProjectionStore.d.ts +0 -43
  55. package/dist/core/PeerProjectionStore.js +0 -327
  56. package/dist/core/PlutoRTC.d.ts +0 -13
  57. package/dist/core/PlutoRTC.js +0 -26
  58. package/dist/core/Room.d.ts +0 -47
  59. package/dist/core/Room.js +0 -376
  60. package/dist/core/Signaling.d.ts +0 -39
  61. package/dist/core/Signaling.js +0 -147
  62. package/dist/core/bridges/BridgeCodecs.d.ts +0 -19
  63. package/dist/core/bridges/BridgeCodecs.js +0 -317
  64. package/dist/core/bridges/BrowserFirestoreRooms.d.ts +0 -36
  65. package/dist/core/bridges/BrowserFirestoreRooms.js +0 -169
  66. package/dist/core/bridges/BrowserFirestoreSignaling.d.ts +0 -111
  67. package/dist/core/bridges/BrowserFirestoreSignaling.js +0 -1010
  68. package/dist/core/bridges/NativeIpcBridge.d.ts +0 -156
  69. package/dist/core/bridges/NativeIpcBridge.js +0 -1472
  70. package/dist/core/bridges/RtdbPresence.d.ts +0 -122
  71. package/dist/core/bridges/RtdbPresence.js +0 -201
  72. package/dist/core/bridges/TauriBridge.d.ts +0 -8
  73. package/dist/core/bridges/TauriBridge.js +0 -7
  74. package/dist/core/bridges/WasmBridge.d.ts +0 -233
  75. package/dist/core/bridges/WasmBridge.js +0 -1811
  76. package/dist/core/config.d.ts +0 -31
  77. package/dist/core/config.js +0 -138
  78. package/dist/core/transports/ITransport.d.ts +0 -12
  79. package/dist/core/transports/ITransport.js +0 -1
  80. package/dist/core/transports/LocalDaemonBridge.d.ts +0 -41
  81. package/dist/core/transports/LocalDaemonBridge.js +0 -227
  82. package/dist/core/transports/TauriSignaling.d.ts +0 -28
  83. package/dist/core/transports/TauriSignaling.js +0 -373
  84. package/dist/core/transports/TransportFactory.d.ts +0 -9
  85. package/dist/core/transports/TransportFactory.js +0 -59
  86. package/dist/core/transports/WasmSignaling.d.ts +0 -78
  87. package/dist/core/transports/WasmSignaling.js +0 -522
  88. package/dist/core/transports/WebRTCTransport.d.ts +0 -23
  89. package/dist/core/transports/WebRTCTransport.js +0 -132
  90. package/dist/core/trust.d.ts +0 -23
  91. package/dist/core/trust.js +0 -99
  92. package/dist/core/types.js +0 -19
  93. package/dist/moq/MoQMediaTransport.d.ts +0 -6
  94. package/dist/moq/MoQMediaTransport.js +0 -106
  95. package/dist/moq/MoQPublisher.d.ts +0 -22
  96. package/dist/moq/MoQPublisher.js +0 -179
  97. package/dist/moq/MoQSession.d.ts +0 -35
  98. package/dist/moq/MoQSession.js +0 -166
  99. package/dist/moq/MoQSubscriber.d.ts +0 -19
  100. package/dist/moq/MoQSubscriber.js +0 -235
  101. package/dist/moq/common.d.ts +0 -47
  102. package/dist/moq/common.js +0 -304
  103. package/dist/moq/messages.d.ts +0 -105
  104. package/dist/moq/messages.js +0 -367
  105. package/dist/presets/plutoHosted.d.ts +0 -13
  106. package/dist/presets/plutoHosted.js +0 -18
  107. package/dist/runtime/DelegatingRuntimeAdapter.d.ts +0 -68
  108. package/dist/runtime/DelegatingRuntimeAdapter.js +0 -250
  109. package/dist/runtime/IpcRuntimeAdapter.d.ts +0 -9
  110. package/dist/runtime/IpcRuntimeAdapter.js +0 -13
  111. package/dist/runtime/RuntimeClient.d.ts +0 -257
  112. package/dist/runtime/RuntimeClient.js +0 -1484
  113. package/dist/runtime/TauriRuntimeAdapter.d.ts +0 -1
  114. package/dist/runtime/TauriRuntimeAdapter.js +0 -1
  115. package/dist/runtime/factories.d.ts +0 -24
  116. package/dist/runtime/factories.js +0 -66
  117. package/dist/runtime/ipc.d.ts +0 -8
  118. package/dist/runtime/ipc.js +0 -65
  119. package/dist/runtime/ipcContract.d.ts +0 -46
  120. package/dist/runtime/ipcContract.js +0 -1
  121. package/dist/runtime/types.d.ts +0 -110
  122. package/dist/runtime/types.js +0 -1
  123. package/dist/transports/TauriTransport.d.ts +0 -17
  124. package/dist/transports/TauriTransport.js +0 -49
  125. package/dist/transports/WebTransport.d.ts +0 -23
  126. package/dist/transports/WebTransport.js +0 -71
  127. package/dist/utils/debug.d.ts +0 -4
  128. package/dist/utils/debug.js +0 -33
  129. package/dist/utils/runtime.d.ts +0 -1
  130. package/dist/utils/runtime.js +0 -10
@@ -0,0 +1,1041 @@
1
+ import { l as ChannelDescriptor$1, i as ProtocolName, L as LocalDeviceInfo, I as IncomingStreamChannelMetadata, k as ClientOptions, m as Device, n as SignalingSession, o as RuntimeIdentity, p as DeviceStatusSnapshot, M as ManagedDeviceConnectOptions, q as PeerState, r as PeerHealth, J as JoinRoomOptions, s as RoomMember, t as PeerScope, B as BackendConnectionState, A as AuthContext, u as PeerLifecycleStatus, P as PeerSessionSnapshot, v as ConnectionOptions, G as GrantScope, w as ISignalingBackend, c as RuntimeCapabilities, a as ConnectDeviceHooks, b as ConnectDeviceOptions, C as ConnectDeviceResult, x as ManagedConnectionRecord, R as ResolvedPeerIdentity, d as AppLimits, N as NativeConnectResult, E as ExplicitFileDataSendParams } from './DelegatingRuntimeAdapter-CW8d78dZ.js';
2
+ import { P as PlutoIpcBridge, I as IpcRuntimeAdapter } from './IpcRuntimeAdapter-CT-W0Mtp.js';
3
+ import { WasmRuntimeAdapter } from './runtime/WasmRuntimeAdapter.js';
4
+
5
+ /**
6
+ * App-facing options intentionally hide transport node identifiers from callbacks.
7
+ */
8
+ type RuntimeClientOptions = Omit<ClientOptions, 'onDevices' | 'onAutoConnect' | 'onIncomingSession'> & {
9
+ onDevices?: (devices: RuntimeDevice[]) => void;
10
+ onAutoConnect?: (devices: RuntimeDevice[]) => void;
11
+ onIncomingSession?: (session: RuntimeSession) => Promise<void>;
12
+ };
13
+ /**
14
+ * App-facing device model. Runtime transport identifiers stay internal.
15
+ */
16
+ type RuntimeDevice = Omit<Device, 'nodeId'>;
17
+ /**
18
+ * App-facing session model. Node identifiers are runtime-internal metadata.
19
+ */
20
+ type RuntimeSession = Omit<SignalingSession, 'initiatorNodeId' | 'targetNodeId' | 'appTag'>;
21
+ type RuntimeAuthIdentity = RuntimeIdentity;
22
+ type RuntimeAuthContext = AuthContext;
23
+ /**
24
+ * App-facing peer state model. Runtime transport identifiers stay internal.
25
+ */
26
+ type RuntimePeerState = Omit<PeerState, 'nodeId'>;
27
+ type RuntimePeerHealth = PeerHealth;
28
+ type RuntimePeerLifecycleStatus = PeerLifecycleStatus;
29
+ type RuntimePeerScope = PeerScope;
30
+ /**
31
+ * App-facing peer session snapshot model. Runtime transport identifiers stay internal.
32
+ */
33
+ type RuntimePeerSessionSnapshot = Omit<PeerSessionSnapshot, 'nodeId'>;
34
+ type RuntimeLocalDeviceInfo = LocalDeviceInfo;
35
+ type RuntimeRoomMember = RoomMember;
36
+ type RuntimeDeviceConnectOptions = ManagedDeviceConnectOptions;
37
+ type RuntimeJoinRoomOptions = JoinRoomOptions;
38
+ type RuntimeChannelDescriptor = ChannelDescriptor$1;
39
+ interface RuntimeConnectionTarget {
40
+ ticket: string;
41
+ timeoutMs?: number;
42
+ }
43
+ interface RuntimePeerConnectOptions {
44
+ deviceId?: string;
45
+ ticket?: string;
46
+ scope?: RuntimePeerScope;
47
+ channelId?: string;
48
+ }
49
+ interface RuntimePeerStreamOptions {
50
+ ticket?: string;
51
+ scope?: RuntimePeerScope;
52
+ channelId?: string;
53
+ timeoutMs?: number;
54
+ }
55
+ /**
56
+ * App-facing device status snapshot model. Runtime transport identifiers stay internal.
57
+ */
58
+ type RuntimeDeviceStatusSnapshot = Omit<DeviceStatusSnapshot, 'nodeId'>;
59
+ type RuntimeDeviceStatus = RuntimeDeviceStatusSnapshot;
60
+ type RuntimeIncomingStream = {
61
+ type: 'bi' | 'uni';
62
+ stream: any;
63
+ remoteNodeId: string;
64
+ protocolHint?: 'control' | 'explicit' | 'native-main' | 'unknown';
65
+ channel?: IncomingStreamChannelMetadata | null;
66
+ };
67
+ type RuntimeConnectionEvent = {
68
+ type: 'connected' | 'disconnected';
69
+ connectionId: string;
70
+ localNodeId: string;
71
+ remoteNodeId: string;
72
+ transport: ProtocolName;
73
+ };
74
+ type RuntimeRawConnection = {
75
+ connectionId: string;
76
+ localNodeId: string;
77
+ remoteNodeId: string;
78
+ };
79
+ type RuntimePresenceLoopOptions = {
80
+ deviceName?: string;
81
+ ticket?: string;
82
+ metadata?: string;
83
+ };
84
+ type RuntimeManagedSessionPlatform = 'native' | 'web';
85
+ type RuntimeManagedSessionKind = 'app-user-device' | 'share-anonymous' | 'drive-grant-guest' | 'scoped-guest' | (string & {});
86
+ type RuntimeAutoConnectPolicy = 'enabled' | 'disabled' | 'scoped-only';
87
+ type RuntimePresencePolicy = 'online' | 'disabled';
88
+ type RuntimeConnectionStateSnapshot = BackendConnectionState;
89
+ type RuntimeUiConnectionStatus = 'connecting' | 'connected' | 'disconnected' | 'failed';
90
+ interface RuntimePeerReadinessSnapshot {
91
+ requestedId: string;
92
+ connected: boolean;
93
+ settledReady: boolean;
94
+ status: RuntimeUiConnectionStatus;
95
+ health: RuntimePeerHealth | 'unknown';
96
+ deviceId?: string | null;
97
+ deviceIdHint?: string | null;
98
+ activeConnectionId?: string | null;
99
+ readinessState?: string;
100
+ readinessReason?: string;
101
+ scopes: string[];
102
+ }
103
+ interface RuntimeLocalDeviceProfile {
104
+ deviceId: string | null;
105
+ deviceName: string;
106
+ platformType: string;
107
+ userId: string | null;
108
+ capabilities: NonNullable<RuntimeLocalDeviceInfo['capabilities']>;
109
+ lastSeenAt: string;
110
+ localNodeId?: string | null;
111
+ }
112
+ interface RuntimeManagedSessionOptions {
113
+ platform: RuntimeManagedSessionPlatform;
114
+ sessionKind?: RuntimeManagedSessionKind;
115
+ scope?: string | null;
116
+ autoConnectPolicy?: RuntimeAutoConnectPolicy;
117
+ presencePolicy?: RuntimePresencePolicy;
118
+ userId?: string | null;
119
+ deviceName?: string;
120
+ localDeviceId?: string | null;
121
+ metadata?: string;
122
+ autoConnect?: boolean;
123
+ presence?: boolean;
124
+ }
125
+ interface RuntimeManagedSession {
126
+ mode: RuntimeManagedSessionPlatform;
127
+ device: RuntimeLocalDeviceProfile;
128
+ stop: () => Promise<void>;
129
+ }
130
+ type ConnectionTarget = RuntimeConnectionTarget;
131
+ type PeerConnectOptions = RuntimePeerConnectOptions;
132
+ type PeerStreamOptions = RuntimePeerStreamOptions;
133
+ type IncomingStream = RuntimeIncomingStream;
134
+ type ConnectionEvent = RuntimeConnectionEvent;
135
+ type RawConnection = RuntimeRawConnection;
136
+ type PresenceLoopOptions = RuntimePresenceLoopOptions;
137
+ type PeerReadiness = RuntimePeerReadinessSnapshot;
138
+ type DeviceProfile = RuntimeLocalDeviceProfile;
139
+ type SessionOptions$1 = RuntimeManagedSessionOptions;
140
+ type Session$1 = RuntimeManagedSession;
141
+ type ChannelDescriptor = RuntimeChannelDescriptor;
142
+
143
+ interface ITransport {
144
+ readonly name: string;
145
+ readonly isReady: boolean;
146
+ init(localNodeId: string, remoteNodeId: string, options: any): Promise<void>;
147
+ send(data: Uint8Array): Promise<void>;
148
+ close(): void;
149
+ onMessage(callback: (data: Uint8Array) => void): void;
150
+ onStateChange(callback: (state: 'connecting' | 'connected' | 'failed' | 'disconnected') => void): void;
151
+ handleSignalingMessage?(msg: any): void;
152
+ getSignalingHandler?(): (msg: any) => Promise<void>;
153
+ getNativeTransport?(): any;
154
+ getNegotiationId?(): string | null;
155
+ getDataChannelReadyState?(): string | null;
156
+ }
157
+
158
+ type ConnectionHealth = 'unknown' | 'healthy' | 'suspect' | 'stale';
159
+
160
+ type UpgradeState = 'none' | 'upgrading' | 'upgraded' | 'failed';
161
+ declare class Connection {
162
+ private static readonly textDecoder;
163
+ private static readonly textEncoder;
164
+ private static readonly UPGRADE_RETRY_DELAY_MS;
165
+ private static readonly MAX_UPGRADE_RETRIES;
166
+ private static readonly WEBRTC_DISCONNECTED_GRACE_MS;
167
+ private static readonly MAX_PENDING_MESSAGES;
168
+ /**
169
+ * Must exceed `WEBRTC_ICE_CONNECT_TIMEOUT_MS` in `WebRTCTransport`: the transport
170
+ * waits that long for ICE + DataChannel before `failed`. A shorter watchdog here
171
+ * tears the PC down early, burns `MAX_UPGRADE_RETRIES`, and stretches upgrades to ~60s+ under load.
172
+ */
173
+ private static readonly WEBRTC_UPGRADE_ATTEMPT_TIMEOUT_MS;
174
+ private listeners;
175
+ private pendingMessages;
176
+ private webrtcBinaryHandlers;
177
+ private closeListeners;
178
+ private upgradeStateListeners;
179
+ private writer;
180
+ private reader;
181
+ private _isClosed;
182
+ get isClosed(): boolean;
183
+ private receiveBuffer;
184
+ readonly id: string;
185
+ readonly remoteNodeId: string;
186
+ /** @deprecated Compatibility alias for legacy consumers. This is the remote node id, not a device id. */
187
+ readonly deviceId: string;
188
+ readonly localNodeId: string;
189
+ private options;
190
+ private writeMutex;
191
+ private nativeSignalSender;
192
+ private webrtcTransport;
193
+ private upgradeState;
194
+ private upgradeRequested;
195
+ private upgradeAttemptActive;
196
+ private upgradeRetryCount;
197
+ private upgradeRetryTimer;
198
+ private upgradeAttemptTimeoutTimer;
199
+ private lastReportedTransportStatus;
200
+ private upgradeTerminalFailure;
201
+ private pendingSignals;
202
+ private activeNegotiationId;
203
+ private webrtcHeartbeat;
204
+ private webRtcHeartbeatProbeInFlight;
205
+ private webRtcHeartbeatConsecutiveProbeFailures;
206
+ private irohHealthListeners;
207
+ private webrtcHealthListeners;
208
+ private lastWebRtcHeartbeatOkAt;
209
+ private lastWebRtcDataChannelOpenAt;
210
+ private lastForegroundAt;
211
+ private webRtcDisconnectedGraceTimer;
212
+ private preferredWebRtcRole;
213
+ constructor(id: string, localNodeId: string, remoteNodeId: string, writer: WritableStreamDefaultWriter<Uint8Array>, reader: ReadableStreamDefaultReader<Uint8Array>, options?: ConnectionOptions);
214
+ /**
215
+ * Starts WebRTC upgrade only when peer capability negotiation allows it.
216
+ * No-op when WebRTC is not configured or an upgrade already started.
217
+ */
218
+ requestWebRTCUpgrade(reason?: string): void;
219
+ requestTransportRecovery(reason: string, options?: {
220
+ forceRenegotiate?: boolean;
221
+ replaceExisting?: boolean;
222
+ }): void;
223
+ private static readonly FOREGROUND_PROBE_TIMEOUT_MS;
224
+ handleAppForeground(): void;
225
+ private beginWebRtcRecovery;
226
+ getUpgradeState(): UpgradeState;
227
+ updateRTCConfig(rtcConfig: ConnectionOptions['rtcConfig']): void;
228
+ onUpgradeStateChange(callback: (state: UpgradeState) => void): void;
229
+ /**
230
+ * Best-effort transport diagnostics for developer tooling.
231
+ *
232
+ * - `usesRelay=true` means the selected WebRTC candidate pair includes a relay candidate.
233
+ * - `usesRelay=false` means we found a selected pair and it is direct.
234
+ * - `usesRelay=null` means there is not enough data yet.
235
+ */
236
+ getTransportDiagnostics(): Promise<{
237
+ activeTransport: ProtocolName;
238
+ parallelTransport: ProtocolName | null;
239
+ usesRelay: boolean | null;
240
+ relaySource: string | null;
241
+ webrtc: {
242
+ iceConnectionState: string | null;
243
+ iceGatheringState: string | null;
244
+ localCandidateType: string | null;
245
+ remoteCandidateType: string | null;
246
+ localProtocol: string | null;
247
+ remoteProtocol: string | null;
248
+ candidateTypeSummary: string | null;
249
+ } | null;
250
+ }>;
251
+ get transportType(): ProtocolName;
252
+ private _peerMoQReady;
253
+ get peerMoQReady(): boolean;
254
+ set peerMoQReady(value: boolean);
255
+ private _remoteSupportsWebRTC;
256
+ get remoteSupportsWebRTC(): boolean;
257
+ set remoteSupportsWebRTC(value: boolean);
258
+ private mediaListeners;
259
+ /**
260
+ * Send a message to the other peer.
261
+ * Messages can be strings or objects (JSON stringified).
262
+ */
263
+ send(message: string | object | ArrayBuffer | Uint8Array): Promise<void>;
264
+ /**
265
+ * Send media data (video/audio header + payload)
266
+ * Internal use for now.
267
+ */
268
+ sendMedia(type: 'audio' | 'video', data: Uint8Array): Promise<void>;
269
+ /**
270
+ * Send a data message on a specific transport without fallback.
271
+ * Throws when the requested transport is unavailable.
272
+ */
273
+ sendOnTransport(transport: ProtocolName, message: string | object | ArrayBuffer | Uint8Array): Promise<void>;
274
+ /**
275
+ * Write an already-framed payload directly on the underlying iroh control stream.
276
+ * Used by native-main signaling paths that must preserve protocol framing.
277
+ */
278
+ sendRawIrohFrame(frame: Uint8Array): Promise<void>;
279
+ /**
280
+ * Return currently usable transports for this connection.
281
+ */
282
+ getAvailableTransports(): ProtocolName[];
283
+ onWebRTCBinaryMessage(handler: (data: Uint8Array) => boolean): void;
284
+ getWebRTCTransport(): ITransport | null;
285
+ sendOnWebRTC(data: Uint8Array): Promise<void>;
286
+ private encodePayload;
287
+ private buildFrame;
288
+ private sendOverIroh;
289
+ private sendUsingTransport;
290
+ private sendTypedOnTransport;
291
+ private sendTyped;
292
+ /**
293
+ * Disconnect the connection
294
+ */
295
+ disconnect(): Promise<void>;
296
+ /**
297
+ * Listen for incoming messages
298
+ */
299
+ onMessage(callback: (message: any) => void): void;
300
+ /**
301
+ * Listen for incoming media
302
+ */
303
+ onMedia(callback: (type: 'audio' | 'video', data: Uint8Array) => void): void;
304
+ /**
305
+ * Listen for disconnection
306
+ */
307
+ onDisconnect(callback: () => void): void;
308
+ private close;
309
+ private preserveWebRtcConnectionAfterBaseTransportLoss;
310
+ private readLoop;
311
+ injectData(chunk: Uint8Array): void;
312
+ private handleData;
313
+ private static isUntypedDataFrame;
314
+ private processDataPayload;
315
+ private isLikelyTextPayload;
316
+ private emitMedia;
317
+ private emitMessage;
318
+ receiveMessage(msg: any): void;
319
+ receiveDataPayload(messageData: Uint8Array): void;
320
+ private trackListeners;
321
+ addTrack(track: MediaStreamTrack): RTCRtpSender | null;
322
+ addTransceiver(trackOrKind: MediaStreamTrack | string, init?: RTCRtpTransceiverInit): RTCRtpTransceiver | null;
323
+ onTrack(callback: (event: RTCTrackEvent) => void): void;
324
+ private hasRecoverableBasePath;
325
+ private isWebRtcDataChannelOpen;
326
+ private clearWebRtcDisconnectedGraceTimer;
327
+ private transportStillLikelyAlive;
328
+ private handleDisconnectedTransportStateWithGrace;
329
+ private attemptUpgrade;
330
+ private setUpgradeState;
331
+ private handleUpgradeFailure;
332
+ private shouldRetryUpgrade;
333
+ private scheduleUpgradeRetry;
334
+ private clearUpgradeRetryTimer;
335
+ private startUpgradeAttemptTimeout;
336
+ private clearUpgradeAttemptTimeoutTimer;
337
+ private teardownWebRTCTransport;
338
+ private startWebRtcHeartbeat;
339
+ private stopWebRtcHeartbeat;
340
+ private sendIrohHeartbeatPong;
341
+ /** Register a listener for WebRTC heartbeat health changes. */
342
+ onWebRtcHeartbeatHealth(cb: (health: ConnectionHealth) => void): void;
343
+ /** Register a listener for iroh heartbeat health changes (WASM path). */
344
+ onIrohHeartbeatHealth(cb: (health: ConnectionHealth) => void): void;
345
+ reportTransportStatusIfChanged(): void;
346
+ private resolveParallelTransport;
347
+ setNativeSignalSender(sender: (envelope: any) => Promise<void>): void;
348
+ private sendInternalSignal;
349
+ receiveInternalSignal(content: any): void;
350
+ private handleInternalSignal;
351
+ private createNegotiationId;
352
+ private getDeterministicWebRtcRole;
353
+ private normalizeNegotiationId;
354
+ }
355
+
356
+ interface SessionOptions {
357
+ /**
358
+ * Logical purpose of this session. Used as a peer-scope tag on all
359
+ * outbound connections. Incoming events are filtered to peers carrying
360
+ * this scope (or all peers when `allowAllPeers` is true).
361
+ */
362
+ scope: string;
363
+ /**
364
+ * When true, watchPeerStates / onConnectionStateChange deliver events for
365
+ * ALL peers, not just those scoped to this session. Useful for the default
366
+ * 'user-device' session that legitimately needs the full peer picture.
367
+ * Default: false.
368
+ */
369
+ allowAllPeers?: boolean;
370
+ /**
371
+ * Additional peer IDs (node IDs, device IDs, connection IDs) that this
372
+ * session is permitted to observe, independent of their scope tags.
373
+ * Useful for magic-link sessions that know the host's node ID from the
374
+ * ticket before a connection exists.
375
+ */
376
+ allowPeers?: ReadonlyArray<string>;
377
+ }
378
+ /** Disposable scope-filtered view over a shared RuntimeClient. */
379
+ interface Session {
380
+ readonly scope: string;
381
+ readonly disposed: boolean;
382
+ /**
383
+ * Subscribe to peer-state snapshots filtered to this session's scope.
384
+ * The callback fires once immediately with the current filtered snapshot,
385
+ * then again whenever relevant peer state changes.
386
+ */
387
+ watchPeerStates(callback: (peers: RuntimePeerState[]) => void): () => void;
388
+ /**
389
+ * Subscribe to connection-state events filtered to this session's scope.
390
+ * Returns the unsubscribe function (may be async for WASM bridge compat).
391
+ */
392
+ onConnectionStateChange(callback: (state: RuntimeConnectionStateSnapshot) => void): (() => void) | Promise<() => void>;
393
+ /** Async snapshot of peers matching this session's scope. */
394
+ listConnectedPeers(): RuntimePeerState[];
395
+ /** Peer readiness for a specific peer ID (scope-filtered). */
396
+ getPeerReadiness(peerId: string): Promise<RuntimePeerReadinessSnapshot>;
397
+ /**
398
+ * Connect to a peer via ticket or device ID, tagging the connection with
399
+ * this session's scope.
400
+ */
401
+ connectPeer(options: RuntimePeerConnectOptions): Promise<Connection>;
402
+ /** Disconnect a peer within this session's scope only. */
403
+ disconnectPeer(peerId: string): Promise<void>;
404
+ /**
405
+ * Subscribe to incoming streams from peers whose scope matches this
406
+ * session. Streams from other scopes are not delivered.
407
+ */
408
+ onIncomingStream(callback: (stream: RuntimeIncomingStream) => void): () => void;
409
+ /** Tear down all subscriptions and disconnect scope-tagged connections. */
410
+ dispose(): void;
411
+ }
412
+ declare class ScopedSession implements Session {
413
+ readonly scope: string;
414
+ private _disposed;
415
+ private readonly runtime;
416
+ private readonly allowAllPeers;
417
+ private readonly allowedPeerIds;
418
+ private readonly cleanups;
419
+ constructor(runtime: RuntimeClient, options: SessionOptions);
420
+ get disposed(): boolean;
421
+ /** Returns true when this session should receive events for this peer. */
422
+ private matchesPeer;
423
+ private matchesConnectionState;
424
+ private matchesStream;
425
+ watchPeerStates(callback: (peers: RuntimePeerState[]) => void): () => void;
426
+ onConnectionStateChange(callback: (state: RuntimeConnectionStateSnapshot) => void): (() => void) | Promise<() => void>;
427
+ listConnectedPeers(): RuntimePeerState[];
428
+ getPeerReadiness(peerId: string): Promise<RuntimePeerReadinessSnapshot>;
429
+ connectPeer(options: RuntimePeerConnectOptions): Promise<Connection>;
430
+ disconnectPeer(peerId: string): Promise<void>;
431
+ onIncomingStream(callback: (stream: RuntimeIncomingStream) => void): () => void;
432
+ dispose(): void;
433
+ private assertNotDisposed;
434
+ }
435
+
436
+ /**
437
+ * Phase 4 of the OpenRTC auth + connection remediation plan
438
+ * (`docs/plans/openrtc-auth-connection-remediation-plan.md`).
439
+ *
440
+ * `DriveGrantActorHandle` is the TS mirror of the Rust
441
+ * `DriveGrantConnectionActor` (see `openrtc/crates/openrtc/src/client/drive_grant_actor.rs`).
442
+ * It is the single observer-facing API for drive-grant guest connections:
443
+ * `DriveViewClient`, `DriveShareRedeemPage`, and friends call this handle
444
+ * instead of dialing/retrying directly. With one handle per
445
+ * `(scope, peerNodeId)` key, multiple requesters that share a connection
446
+ * coalesce their `ensureReady()` calls onto a single underlying dial —
447
+ * removing the lifecycle-replacement race documented in `logs-desktop-A.md`.
448
+ *
449
+ * ## Scope
450
+ *
451
+ * Phase 4 lands the handle + `RuntimeClient.getDriveGrantActor` accessor
452
+ * + observer-side rewiring. The actor is **not yet** wired into the
453
+ * underlying Rust dial path — the legacy `connectPeer` codepath continues
454
+ * to run (Phase 7 flips that). What changes today:
455
+ *
456
+ * - `DriveViewClient.ensureGrantConnected` calls
457
+ * `runtimeClient.getDriveGrantActor(scope, peerNodeId).ensureReady()`,
458
+ * then performs its existing `connectPeer` call inside the
459
+ * handle-owned `dial` function. Multiple concurrent observers for the
460
+ * same key thus coalesce to one `connectPeer` call.
461
+ * - `DeviceContext` for `app-user-device` is bit-for-bit unchanged —
462
+ * this file only loads when `sessionKind === 'drive-grant-guest'`.
463
+ *
464
+ * ## Coalescing semantics
465
+ *
466
+ * `ensureReady()` is the canonical "is the connection up?" call:
467
+ *
468
+ * - If the underlying dial is in flight, all callers await the same
469
+ * promise.
470
+ * - If the underlying dial succeeded, callers resolve immediately.
471
+ * - If the underlying dial failed, the handle stays "not ready" and the
472
+ * next caller may try again.
473
+ * - If `shutdown()` was called, every caller (current + future) rejects
474
+ * with `ActorError.Shutdown`.
475
+ *
476
+ * The only state machine transitions are:
477
+ *
478
+ * `idle` --(ensureReady)--> `dialing` --(success)--> `ready`
479
+ * | --(failure)--> `idle`
480
+ * `<any>` --(shutdown)--> `closed`
481
+ *
482
+ * The Rust actor enforces the same shape; the two are intentionally kept
483
+ * isomorphic so Phase 7 can collapse the TS handle into a thin observer
484
+ * over the Rust actor without changing call sites.
485
+ */
486
+ type DriveGrantActorErrorKind = 'shutdown' | 'dial-failed' | 'not-ready' | 'logical-channel-not-implemented';
487
+ declare class DriveGrantActorError extends Error {
488
+ readonly kind: DriveGrantActorErrorKind;
489
+ constructor(kind: DriveGrantActorErrorKind, message: string);
490
+ }
491
+ type DriveGrantWebRtcState = 'unknown' | 'disabled' | 'connecting' | 'connected' | 'failed';
492
+ interface DriveGrantConnectionKey {
493
+ scope: string;
494
+ peerNodeId: string;
495
+ }
496
+ declare function driveGrantConnectionKey(scope: string, peerNodeId: string): DriveGrantConnectionKey;
497
+ declare function driveGrantConnectionKeyToString(key: DriveGrantConnectionKey): string;
498
+ /**
499
+ * The dial function the handle calls when no connection has yet
500
+ * resolved. Must be idempotent: returning when a healthy transport
501
+ * exists, throwing only on transient failure (caller retries) or
502
+ * permanent failure (caller surfaces).
503
+ */
504
+ type DriveGrantDial = (key: DriveGrantConnectionKey) => Promise<void>;
505
+ /**
506
+ * Optional teardown hook invoked on `shutdown()`. Default is a no-op.
507
+ */
508
+ type DriveGrantClose = (key: DriveGrantConnectionKey) => Promise<void>;
509
+ interface DriveGrantActorHandleOptions {
510
+ key: DriveGrantConnectionKey;
511
+ dial: DriveGrantDial;
512
+ close?: DriveGrantClose;
513
+ }
514
+ interface DriveGrantLogicalChannelHandle {
515
+ label: string;
516
+ }
517
+ type WebRtcListener = (state: DriveGrantWebRtcState) => void;
518
+ declare class DriveGrantActorHandle {
519
+ readonly key: DriveGrantConnectionKey;
520
+ private readonly dial;
521
+ private readonly close;
522
+ private state;
523
+ private inFlight;
524
+ private webrtcState;
525
+ private webrtcListeners;
526
+ constructor(options: DriveGrantActorHandleOptions);
527
+ /** Returns true if the actor has resolved a successful dial and is not shut down. */
528
+ isReady(): boolean;
529
+ /** Returns true after `shutdown()` has been called. */
530
+ isClosed(): boolean;
531
+ /**
532
+ * Phase 7 correlation context. Always populated with
533
+ * `sessionKind=drive-grant-guest`, `scope`, `peerNodeId`, and
534
+ * (when the scope encodes one) `grantId`.
535
+ */
536
+ private correlation;
537
+ /**
538
+ * Coalesce-and-dial. N concurrent callers resolve via a single
539
+ * underlying dial. After the first success this is a fast no-op until
540
+ * `shutdown()` flips state to `closed`.
541
+ */
542
+ ensureReady(): Promise<void>;
543
+ /** Subscribe to WebRTC adoption state. Returns an unsubscribe fn. */
544
+ observeWebRtc(listener: WebRtcListener): () => void;
545
+ /** Current WebRTC state without subscribing. */
546
+ getWebRtcState(): DriveGrantWebRtcState;
547
+ /**
548
+ * Test/Phase-7 hook: lifecycle code that learns of a WebRTC state
549
+ * transition pushes it via this method so observers see the change.
550
+ */
551
+ setWebRtcState(state: DriveGrantWebRtcState): void;
552
+ /**
553
+ * Phase 6: returns a logical channel handle backed by the base iroh
554
+ * transport. The host-side `DriveViewBaseIrohHandler` dispatches
555
+ * drive-view frames arriving on a bi-stream with label `"drive-view"`,
556
+ * so logical channels are implicitly multiplexed by the underlying
557
+ * QUIC stream layer.
558
+ */
559
+ openLogicalChannel(label: string): Promise<DriveGrantLogicalChannelHandle>;
560
+ /**
561
+ * Test/Phase-4 helper: returns the label without invoking the
562
+ * unimplemented wire format, so observers can prove their request
563
+ * shape round-trips today.
564
+ */
565
+ openLogicalChannelTestStub(label: string): Promise<DriveGrantLogicalChannelHandle>;
566
+ /**
567
+ * Idempotent shutdown. Subsequent `ensureReady()` rejects with
568
+ * `shutdown`; subsequent `shutdown()` is a no-op. Observers receive
569
+ * a final `'failed'` state so they can wire teardown side-effects.
570
+ */
571
+ shutdown(): Promise<void>;
572
+ }
573
+ /**
574
+ * Registry that hands out one shared `DriveGrantActorHandle` per
575
+ * `DriveGrantConnectionKey`. `getOrSpawn` is idempotent.
576
+ */
577
+ declare class DriveGrantActorRegistry {
578
+ private actors;
579
+ private readonly factory;
580
+ constructor(factory: (key: DriveGrantConnectionKey) => DriveGrantActorHandle);
581
+ getOrSpawn(key: DriveGrantConnectionKey, factoryOverride?: (key: DriveGrantConnectionKey) => DriveGrantActorHandle): DriveGrantActorHandle;
582
+ get(key: DriveGrantConnectionKey): DriveGrantActorHandle | null;
583
+ /** Tear down every actor; clears the registry. */
584
+ shutdownAll(): Promise<void>;
585
+ size(): number;
586
+ }
587
+
588
+ interface RuntimePolicySnapshot {
589
+ managedSession: {
590
+ nativeStartRetryWindowMs: number;
591
+ nativeStartRetryMinDelayMs: number;
592
+ nativeStartRetryMaxDelayMs: number;
593
+ reconciliationIntervalMs: number;
594
+ deviceStatusRefreshDebounceMs: number;
595
+ };
596
+ browserAutoConnect: {
597
+ scanDebounceMs: number;
598
+ retryCooldownMs: number;
599
+ settleGuardMs: number;
600
+ retryMaxMs: number;
601
+ nonInitiatorBaseGraceMs: number;
602
+ nonInitiatorMaxGraceMs: number;
603
+ };
604
+ nativeIpc: {
605
+ authRequiredWaitMs: number;
606
+ managedSessionIpcTimeoutMs: number;
607
+ managedSessionIpcMaxAttempts: number;
608
+ connectionEventSubscribeWindowMs: number;
609
+ connectionEventRetryMinDelayMs: number;
610
+ connectionEventRetryMaxDelayMs: number;
611
+ tauriIpcNegativeCacheMs: number;
612
+ };
613
+ browserIdentity: {
614
+ ephemeralDeviceIdTtlMs: number;
615
+ };
616
+ }
617
+ declare const OPENRTC_RUNTIME_POLICY: RuntimePolicySnapshot;
618
+ declare function getRuntimePolicy(): RuntimePolicySnapshot;
619
+
620
+ /**
621
+ * RuntimeClient is the primary application-facing API.
622
+ * It owns host/runtime orchestration on top of the Rust core and should be the
623
+ * only high-level surface consumed by product code. App code should not rebuild
624
+ * lifecycle, discovery, or transfer-readiness policy above this layer.
625
+ *
626
+ * Allowed:
627
+ * - app-facing session startup/shutdown
628
+ * - typed device, peer, room, and transfer APIs
629
+ * - thin host/runtime coordination
630
+ *
631
+ * Not allowed:
632
+ * - teaching app code to depend on `advanced.unwrap*()`
633
+ * - treating `nodeId` as high-level peer identity
634
+ * - reimplementing Rust-owned lifecycle policy in product code
635
+ *
636
+ * Source of truth:
637
+ * - Rust core owns transport lifecycle, connection health, and native signaling surfaces
638
+ * - Browser discovery/presence/signaling are host-owned by the scoped TypeScript Firebase adapters
639
+ * - RuntimeClient should converge toward thin wrappers over those runtime/backing surfaces
640
+ */
641
+ declare class RuntimeClient {
642
+ private static readonly NATIVE_START_RETRY_WINDOW_MS;
643
+ private static readonly NATIVE_START_RETRY_MIN_DELAY_MS;
644
+ private static readonly NATIVE_START_RETRY_MAX_DELAY_MS;
645
+ private static readonly MANAGED_RECONCILIATION_INTERVAL_MS;
646
+ private static readonly DEVICE_STATUS_REFRESH_DEBOUNCE_MS;
647
+ private static readonly MANAGED_USER_DEVICE_SCOPE;
648
+ static readonly MANAGED_FRIEND_SCOPE: GrantScope;
649
+ private readonly client;
650
+ private readonly backend;
651
+ private readonly deviceManager;
652
+ private readonly peerManager;
653
+ private readonly connectionController;
654
+ private managedSessionKey;
655
+ private managedSessionUserId;
656
+ private managedSessionOptions;
657
+ private managedSessionTransition;
658
+ private managedSessionStartInFlight;
659
+ private readonly managedReconciliationTasks;
660
+ /**
661
+ * Phase 4: per-`{scope, peerNodeId}` scoped-connection actor registry.
662
+ * Lazily created; `null` until an observer first calls `getDriveGrantActor`
663
+ * (legacy name) or `getScopedConnectionActor` (generic alias).
664
+ *
665
+ * Note: persistent same-account auto-connect (`app-user-device`) and
666
+ * anonymous share flows (`share-anonymous`) do not use this coalescer.
667
+ */
668
+ private driveGrantActorRegistry;
669
+ private static describeTicketForLogs;
670
+ private serializeManagedSessionOperation;
671
+ constructor(options: RuntimeClientOptions, backend?: ISignalingBackend | null);
672
+ get identity(): RuntimeAuthIdentity | null;
673
+ private resolveManagedSessionUserId;
674
+ private resolveManagedAutoConnectEnabled;
675
+ private resolveManagedPresenceEnabled;
676
+ private getEffectiveRuntimeUserId;
677
+ private sleep;
678
+ private fetchAndApplyAppLimits;
679
+ private resolvePeerStreamTarget;
680
+ private compatPeerConnectionFromTarget;
681
+ private nextNativeStartRetryDelayMs;
682
+ private hasManagedSession;
683
+ private usesNativeIpcBackend;
684
+ private startManagedReconciliation;
685
+ private notifyManagedReconciliation;
686
+ reconcileNativeManagedSession(reason?: string): Promise<void>;
687
+ private connectionStateSnapshotKey;
688
+ private runNativeStartLoop;
689
+ private isUnsupportedRuntimeAdapterError;
690
+ onIdentityChange(callback: (identity: RuntimeAuthIdentity | null) => void): () => void;
691
+ signInAnonymously(): Promise<void>;
692
+ signInWithPluto(): Promise<void>;
693
+ setAuthContext(context: AuthContext | null): Promise<void>;
694
+ signOut(): Promise<void>;
695
+ initialize(): Promise<void>;
696
+ getRuntimeStatus(): Promise<{
697
+ runtime: 'tauri' | 'browser' | 'unknown';
698
+ wasmLoaded: boolean;
699
+ localNodeId?: string;
700
+ userId?: string;
701
+ }>;
702
+ getRuntimePolicy(): RuntimePolicySnapshot;
703
+ getRuntimeCapabilities(): RuntimeCapabilities;
704
+ start(options?: {
705
+ clearSessionTokens?: boolean;
706
+ }): Promise<void>;
707
+ stop(): void;
708
+ getNodeId(): Promise<string>;
709
+ getNodeIdFromTicket(ticket: string): Promise<string | null>;
710
+ getLocalDeviceId(): Promise<string | null>;
711
+ getLocalDeviceInfo(): Promise<RuntimeLocalDeviceInfo | null>;
712
+ getLocalDeviceProfile(options?: {
713
+ deviceName?: string;
714
+ localDeviceId?: string | null;
715
+ platform?: 'native' | 'web';
716
+ userId?: string | null;
717
+ }): Promise<RuntimeLocalDeviceProfile>;
718
+ updateLocalDeviceName(deviceName: string): Promise<RuntimeLocalDeviceInfo | null>;
719
+ getManagedNodeId(options?: {
720
+ initializeIfMissing?: boolean;
721
+ }): Promise<string | null>;
722
+ getTicket(): Promise<string>;
723
+ /**
724
+ * Generate a session-scoped endpoint ticket with an embedded random token.
725
+ * The token gates incoming connections: only clients that present the token
726
+ * in their handshake are accepted while the registry is non-empty.
727
+ *
728
+ * @param grantScope Admission-grant label for bulk revoke (e.g. "share").
729
+ * This is distinct from `PeerScope`, which only labels peer lifecycle.
730
+ * @param maxConnections 0 = unlimited.
731
+ */
732
+ getTicketWithToken(grantScope: GrantScope, maxConnections?: number): Promise<string>;
733
+ /** Revoke all session tokens that match the given scope. */
734
+ revokeTokensByScope(grantScope: GrantScope): Promise<string[]>;
735
+ private revokeTokensByScopeInternal;
736
+ /** Revoke a single session token by its raw value. */
737
+ revokeSessionToken(token: string): void;
738
+ /**
739
+ * Watch devices belonging to friend users via the browser Firestore
740
+ * signaling backend. Sets up one listener per friend UID.
741
+ *
742
+ * Only works when the signaling backend supports `watchFriendDevices`.
743
+ * For native backends, friend device discovery should be handled
744
+ * at the application layer (e.g., FriendDeviceContext).
745
+ *
746
+ * @param friendUserIds - Array of friend user IDs to watch
747
+ * @param callback - Called with the merged map of friend devices
748
+ * @returns Cleanup function
749
+ */
750
+ watchFriendDevices(friendUserIds: string[], callback: (friendDevices: Map<string, RuntimeDevice[]>) => void): () => void;
751
+ /**
752
+ * Get a compound ticket with a friend-scoped grant token.
753
+ * Friends connecting with this ticket are admitted with `friend` scope.
754
+ */
755
+ getFriendTicket(maxConnections?: number): Promise<string>;
756
+ /**
757
+ * Revoke all friend-scoped tokens and disconnect affected connections.
758
+ */
759
+ revokeFriendTokens(): Promise<string[]>;
760
+ /**
761
+ * Update the friend ticket on the current device's presence doc.
762
+ * Call this after minting a friend ticket so that friends watching
763
+ * the device doc can see and use the friend-scoped ticket.
764
+ */
765
+ updateFriendTicket(friendTicket: string | null): Promise<void>;
766
+ getEndpointTicket(): Promise<string>;
767
+ startManagedSession(options: RuntimeManagedSessionOptions): Promise<RuntimeManagedSession>;
768
+ stopManagedSession(options?: {
769
+ preserveBackendSession?: boolean;
770
+ }): Promise<void>;
771
+ private stopManagedSessionInternal;
772
+ private rotateManagedUserDeviceGrant;
773
+ listDevices(): Promise<RuntimeDevice[]>;
774
+ listDevicesWithStatus(): Promise<RuntimeDeviceStatusSnapshot[]>;
775
+ updateDevice(deviceId: string, updates: {
776
+ deviceName?: string;
777
+ capabilities?: RuntimeDevice['capabilities'];
778
+ metadata?: string;
779
+ }): Promise<void>;
780
+ deleteDevice(deviceId: string): Promise<void>;
781
+ watchDevices(callback: (devices: RuntimeDevice[]) => void): () => void;
782
+ watchDevicesWithStatus(callback: (devices: RuntimeDeviceStatusSnapshot[]) => void): () => void;
783
+ connectDeviceWithRetry(device: RuntimeDevice, hooks: ConnectDeviceHooks, options: ConnectDeviceOptions): Promise<ConnectDeviceResult>;
784
+ /**
785
+ * Runtime-owned device connect flow used by product code.
786
+ * Rust owns the actual managed dial policy. This wrapper only:
787
+ * - validates the app-facing device/ticket input
788
+ * - forwards the request to the active runtime adapter
789
+ * - refreshes peer state and invokes optional app callbacks
790
+ */
791
+ connectDevice(device: RuntimeDevice, options: RuntimeDeviceConnectOptions): Promise<ConnectDeviceResult>;
792
+ watchPeerStates(callback: (peers: RuntimePeerState[]) => void): () => void;
793
+ getPeerState(id: string): RuntimePeerState | undefined;
794
+ resolvePeerConnectionRecords(id: string): Promise<ManagedConnectionRecord[]>;
795
+ getPeerSession(id: string): Promise<PeerSessionSnapshot | null>;
796
+ listPeerSessions(): Promise<PeerSessionSnapshot[]>;
797
+ waitForConnectedPeer(id: string, timeoutMs?: number): Promise<PeerSessionSnapshot | null>;
798
+ getPeerReadiness(id: string, timeoutMs?: number): Promise<RuntimePeerReadinessSnapshot>;
799
+ resolvePeerIdentity(id: string): Promise<ResolvedPeerIdentity>;
800
+ resolveIncomingStreamPeer(remoteNodeId: string): Promise<ResolvedPeerIdentity>;
801
+ listConnectedPeers(): RuntimePeerState[];
802
+ addPeerScope(id: string, scope?: string): RuntimePeerState | undefined;
803
+ releasePeerScope(id: string, scope?: string): RuntimePeerState | undefined;
804
+ getPeerScopes(id: string): string[];
805
+ isSamePeer(a: string, b: string): boolean;
806
+ refreshPeerSnapshot(): Promise<RuntimePeerState[]>;
807
+ subscribeSessions(localDeviceId: string, callback: (session: RuntimeSession) => void): Promise<() => void>;
808
+ getAppLimits(): AppLimits;
809
+ createRoom(roomId?: string): Promise<string>;
810
+ joinRoom(roomId: string, options?: RuntimeJoinRoomOptions): Promise<Connection[]>;
811
+ leaveRoom(roomId: string): Promise<void>;
812
+ getRoomMembers(roomId: string): Promise<RuntimeRoomMember[]>;
813
+ watchRoom(roomId: string, callback: (members: RuntimeRoomMember[]) => void): () => void;
814
+ /** @deprecated Use connect() (no-arg) for lifecycle, or connectTo() for peer connections */
815
+ connectByTicket(target: RuntimeConnectionTarget): Promise<Connection>;
816
+ connectPeer(options: RuntimePeerConnectOptions): Promise<Connection>;
817
+ /**
818
+ * Phase 4 of the OpenRTC auth + connection remediation plan:
819
+ * returns the per-`{scope, peerNodeId}` actor handle that
820
+ * drive-grant guest observers (DriveViewClient,
821
+ * DriveShareRedeemPage) coalesce through. The first call for a
822
+ * given key spawns the handle; subsequent calls return the same
823
+ * handle so concurrent observers share a single underlying dial.
824
+ *
825
+ * The handle's `dial` function delegates to this RuntimeClient's
826
+ * existing `connectPeer` API — the actor is purely an observer
827
+ * coalescer in Phase 4. Phase 7 collapses this onto the Rust
828
+ * actor in `Client::drive_grant_actor_registry`.
829
+ *
830
+ * Calling this from `app-user-device` paths is a programming bug
831
+ * — the registry is scoped to drive-grant-guest connections by
832
+ * convention, and same-account auto-connect must not coalesce
833
+ * onto a single shared dial (each device-pair has its own
834
+ * lifecycle).
835
+ */
836
+ getDriveGrantActor(key: DriveGrantConnectionKey | {
837
+ scope: string;
838
+ peerNodeId: string;
839
+ }, options?: {
840
+ /**
841
+ * Compound ticket to dial when the actor's `dial` runs. Used by
842
+ * the default dial that calls `connectPeer` for callers that
843
+ * don't supply a custom `dial`.
844
+ */
845
+ ticket?: string;
846
+ timeoutMs?: number;
847
+ channelId?: string;
848
+ /**
849
+ * Phase 4 escape hatch: callers that need to capture the
850
+ * resolved `Connection` (e.g. `DriveViewClient` wires its
851
+ * router/disconnect handler to the connection object) can
852
+ * supply their own `dial` here. The actor's coalescer still
853
+ * ensures only one `dial(key)` runs even with N concurrent
854
+ * `getDriveGrantActor(...).ensureReady()` callers — this just
855
+ * lets the caller decide what "dial" means.
856
+ */
857
+ dial?: (key: DriveGrantConnectionKey) => Promise<void>;
858
+ }): DriveGrantActorHandle;
859
+ /**
860
+ * Domain-agnostic alias for `getDriveGrantActor`.
861
+ *
862
+ * OpenRTC’s per-`{scope, peerNodeId}` actor is a generic “scoped connection”
863
+ * coalescer. Plutonium’s drive-grant flows were the first adopter, but other
864
+ * app protocols (magic-link, user-device, etc.) may also want the same shape.
865
+ *
866
+ * Backward-compat: this is a thin wrapper with identical behavior.
867
+ */
868
+ getScopedConnectionActor(key: DriveGrantConnectionKey | {
869
+ scope: string;
870
+ peerNodeId: string;
871
+ }, options?: Parameters<RuntimeClient['getDriveGrantActor']>[1]): DriveGrantActorHandle;
872
+ /** Domain-agnostic alias for `shutdownDriveGrantActors`. */
873
+ shutdownScopedConnectionActors(): Promise<void>;
874
+ /**
875
+ * Phase 4: tear down all live drive-grant actors. Called from
876
+ * managed-session teardown so a refresh between drive-grant guest
877
+ * routes does not leak observers across navigations.
878
+ */
879
+ shutdownDriveGrantActors(): Promise<void>;
880
+ openPeerBi(id: string, options?: RuntimePeerStreamOptions): Promise<{
881
+ connection: Connection;
882
+ readable: ReadableStream<Uint8Array>;
883
+ writable: WritableStream<Uint8Array>;
884
+ }>;
885
+ /** Like openPeerBi but skips the settled_ready requirement — usable for latency probes. */
886
+ openPeerBiTransportOnly(id: string, options?: RuntimePeerStreamOptions): Promise<{
887
+ connection: Connection;
888
+ readable: ReadableStream<Uint8Array>;
889
+ writable: WritableStream<Uint8Array>;
890
+ }>;
891
+ openPeerUni(id: string, options?: RuntimePeerStreamOptions): Promise<{
892
+ connection: Connection;
893
+ writable: WritableStream<Uint8Array>;
894
+ }>;
895
+ connectToDevice(params: {
896
+ deviceId?: string | null;
897
+ endpointTicket: string;
898
+ }): Promise<NativeConnectResult>;
899
+ connectRaw(target: RuntimeConnectionTarget): Promise<RuntimeRawConnection>;
900
+ openBi(nodeId: string): Promise<{
901
+ readable: ReadableStream<Uint8Array>;
902
+ writable: WritableStream<Uint8Array>;
903
+ }>;
904
+ openUni(nodeId: string): Promise<WritableStream<Uint8Array>>;
905
+ onIncomingStream(callback: (stream: RuntimeIncomingStream) => boolean | void): () => void;
906
+ registerChannel(descriptor: RuntimeChannelDescriptor): void;
907
+ unregisterChannel(channelId: string): void;
908
+ listChannels(): RuntimeChannelDescriptor[];
909
+ onIncomingChannelStream(channelId: string, callback: (stream: RuntimeIncomingStream) => boolean | void): () => void;
910
+ sendExplicitFilePath(connectionId: string, filePath: string, transferId?: string): Promise<string>;
911
+ sendExplicitFileData(params: ExplicitFileDataSendParams): Promise<void>;
912
+ getTransferHistory(limit?: number): Promise<Array<[string, unknown]>>;
913
+ deleteTransferJob(jobId: string): Promise<void>;
914
+ startPresenceLoop(options?: RuntimePresenceLoopOptions): Promise<void>;
915
+ updatePresence(options?: {
916
+ isOnline?: boolean;
917
+ ttlMs?: number;
918
+ metadata?: string;
919
+ ticket?: string;
920
+ }): Promise<void>;
921
+ setOffline(): Promise<void>;
922
+ cleanupStaleDevices(): Promise<void>;
923
+ startAutoConnect(localDeviceId?: string): Promise<void>;
924
+ isConnected(nodeId: string): Promise<boolean>;
925
+ disconnectNode(nodeId: string): Promise<void>;
926
+ disconnectDevice(deviceId: string): Promise<void>;
927
+ setAutoConnectExcluded(deviceId: string, excluded: boolean): Promise<void>;
928
+ disconnectPeer(id: string, scope?: string): Promise<void>;
929
+ forceDisconnectPeer(id: string): Promise<void>;
930
+ getPeerHealth(id: string): Promise<RuntimePeerHealth>;
931
+ getConnectionStates(): Promise<RuntimeConnectionStateSnapshot[]>;
932
+ onConnectionStateChange(callback: (state: RuntimeConnectionStateSnapshot) => void): Promise<() => void> | (() => void);
933
+ getConnections(): Connection[];
934
+ onConnection(callback: (connection: Connection) => void): () => void;
935
+ onDisconnection(callback: (connection: Connection) => void): () => void;
936
+ onConnectionEvent(callback: (event: RuntimeConnectionEvent) => void): () => void;
937
+ forceReconnectSnapshot(): void;
938
+ /** Single-call lifecycle: combines initialize() + start() */
939
+ connect(): Promise<void>;
940
+ /** Disconnect from the runtime (alias for stop()) */
941
+ disconnect(): void;
942
+ /** Alias for onIdentityChange */
943
+ onAuthChange(callback: (identity: RuntimeAuthIdentity | null) => void): () => void;
944
+ /** Alias for setAuthContext */
945
+ setAuth(context: AuthContext | null): Promise<void>;
946
+ /** Alias for signInWithPluto */
947
+ signIn(): Promise<void>;
948
+ /** Alias for listDevices */
949
+ getDevices(): Promise<RuntimeDevice[]>;
950
+ /** Device subscription with optional status enrichment */
951
+ onDevices(callback: (devices: RuntimeDevice[]) => void): () => void;
952
+ onDevices(callback: (devices: RuntimeDeviceStatusSnapshot[]) => void, options: {
953
+ status: true;
954
+ }): () => void;
955
+ /** Alias for getTicket — returns an invite/ticket string */
956
+ getInvite(): Promise<string>;
957
+ /** Connect to a peer by device ID or options */
958
+ connectTo(options: RuntimePeerConnectOptions): Promise<Connection>;
959
+ /** Alias for waitForConnectedPeer */
960
+ waitFor(id: string, timeoutMs?: number): Promise<PeerSessionSnapshot | null>;
961
+ /** Open a stream to a peer (default: bidirectional) */
962
+ openStream(id: string, options?: RuntimePeerStreamOptions & {
963
+ direction?: 'bi' | 'send';
964
+ }): Promise<{
965
+ connection: Connection;
966
+ readable?: ReadableStream<Uint8Array>;
967
+ writable: WritableStream<Uint8Array>;
968
+ }>;
969
+ openChannelStream(channelId: string, id: string, options?: RuntimePeerStreamOptions & {
970
+ direction?: 'bi' | 'send';
971
+ }): Promise<{
972
+ connection: Connection;
973
+ readable?: ReadableStream<Uint8Array>;
974
+ writable: WritableStream<Uint8Array>;
975
+ }>;
976
+ /** Alias for onIncomingStream */
977
+ onStream(callback: (stream: RuntimeIncomingStream) => boolean | void): () => void;
978
+ onChannelStream(channelId: string, callback: (stream: RuntimeIncomingStream) => boolean | void): () => void;
979
+ /** Alias for watchRoom */
980
+ onRoomChange(roomId: string, callback: (members: RuntimeRoomMember[]) => void): () => void;
981
+ /**
982
+ * Create a scope-filtered session backed by this runtime.
983
+ *
984
+ * The session filters all peer-state and connection-state emissions to
985
+ * peers whose scope tags include `options.scope`, and tags outbound
986
+ * connections with the same scope for the remote side's ACL layer.
987
+ *
988
+ * Disposing the session removes only its own subscriptions and
989
+ * scope-tagged connections — other sessions on this runtime are unaffected.
990
+ *
991
+ * @example
992
+ * // Guest magic-link viewer — sees only the ticket endpoint, never device peers
993
+ * const session = runtime.createSession({ scope: 'magic-link', allowPeers: [ticketNodeId] });
994
+ * session.watchPeerStates(peers => { ... });
995
+ * // On unmount:
996
+ * session.dispose();
997
+ */
998
+ createSession(options: SessionOptions): Session;
999
+ }
1000
+
1001
+ type RuntimeAdapterWithAuth = ISignalingBackend & {
1002
+ setAuthContext?: (context: AuthContext | null) => Promise<void> | void;
1003
+ };
1004
+ type RuntimeFactoryOptions = RuntimeClientOptions;
1005
+ interface PlutoRuntimeAssembly<TBackend extends RuntimeAdapterWithAuth = RuntimeAdapterWithAuth> {
1006
+ runtime: RuntimeClient;
1007
+ identity: any;
1008
+ setAuthContext(context: AuthContext | null): Promise<void>;
1009
+ syncPlutoAuth(options?: {
1010
+ userId?: string | null;
1011
+ forceRefresh?: boolean;
1012
+ }): Promise<void>;
1013
+ bindPlutoAuthHost(): () => void;
1014
+ signInWithPluto(): Promise<void>;
1015
+ signOut(): Promise<void>;
1016
+ stopManagedSession(): Promise<void>;
1017
+ startManagedSession(options: any): Promise<any>;
1018
+ onAuthChange(callback: (identity: any) => void): () => void;
1019
+ getManagedNodeId(options?: {
1020
+ initializeIfMissing?: boolean;
1021
+ }): Promise<string | null>;
1022
+ getRuntimeStatus(): Promise<any>;
1023
+ listDevicesWithStatus(): Promise<any>;
1024
+ watchDevicesWithStatus(callback: (devices: any[]) => void): () => void;
1025
+ connectDevice(device: any, options: any): Promise<any>;
1026
+ setAutoConnectExcluded(deviceId: string, excluded: boolean): Promise<void>;
1027
+ }
1028
+ /**
1029
+ * @deprecated Legacy assembly helper. Use `OpenRTC()` for app code.
1030
+ * Removal target: OpenRTC 0.2.0. This remains available from `openrtc/runtime`
1031
+ * only for advanced integrations that still need `PlutoRuntimeAssembly`.
1032
+ */
1033
+ declare function createWasmClient(options: RuntimeFactoryOptions): PlutoRuntimeAssembly<WasmRuntimeAdapter>;
1034
+ /**
1035
+ * @deprecated Legacy assembly helper. Use `OpenRTC.native()` for app code.
1036
+ * Removal target: OpenRTC 0.2.0. This remains available from `openrtc/runtime`
1037
+ * only for advanced integrations that still need `PlutoRuntimeAssembly`.
1038
+ */
1039
+ declare function createIpcClient(options: RuntimeFactoryOptions, bridge: PlutoIpcBridge): PlutoRuntimeAssembly<IpcRuntimeAdapter>;
1040
+
1041
+ export { DriveGrantActorError as $, type RuntimeAuthIdentity as A, type RuntimeAutoConnectPolicy as B, Connection as C, type DeviceProfile as D, type RuntimeConnectionTarget as E, type RuntimeDeviceStatus as F, type RuntimeJoinRoomOptions as G, type RuntimeManagedSession as H, type IncomingStream as I, type RuntimeManagedSessionKind as J, type RuntimeManagedSessionOptions as K, type RuntimeManagedSessionPlatform as L, type RuntimePeerLifecycleStatus as M, type RuntimePeerScope as N, OPENRTC_RUNTIME_POLICY as O, type PlutoRuntimeAssembly as P, type RuntimePeerSessionSnapshot as Q, type RuntimeClientOptions as R, type RuntimePresenceLoopOptions as S, type RuntimePresencePolicy as T, type RuntimeRoomMember as U, type RuntimeSession as V, type RuntimeUiConnectionStatus as W, ScopedSession as X, type Session as Y, type SessionOptions as Z, getRuntimePolicy as _, RuntimeClient as a, type DriveGrantActorErrorKind as a0, DriveGrantActorHandle as a1, type DriveGrantActorHandleOptions as a2, DriveGrantActorRegistry as a3, type DriveGrantClose as a4, type DriveGrantConnectionKey as a5, type DriveGrantDial as a6, type DriveGrantLogicalChannelHandle as a7, type DriveGrantWebRtcState as a8, type RuntimeFactoryOptions as a9, type Session$1 as aa, type SessionOptions$1 as ab, createIpcClient as ac, createWasmClient as ad, driveGrantConnectionKey as ae, driveGrantConnectionKeyToString as af, type RuntimeDevice as b, type RuntimeDeviceStatusSnapshot as c, type RuntimeDeviceConnectOptions as d, type RuntimeLocalDeviceInfo as e, type RuntimeLocalDeviceProfile as f, type RuntimePeerState as g, type RuntimePeerConnectOptions as h, type RuntimePeerReadinessSnapshot as i, type RuntimePeerHealth as j, type RuntimeChannelDescriptor as k, type RuntimePeerStreamOptions as l, type RuntimeIncomingStream as m, type RuntimePolicySnapshot as n, type RuntimeConnectionStateSnapshot as o, type RuntimeConnectionEvent as p, type RuntimeRawConnection as q, type ChannelDescriptor as r, type ConnectionEvent as s, type ConnectionTarget as t, type PeerConnectOptions as u, type PeerReadiness as v, type PeerStreamOptions as w, type PresenceLoopOptions as x, type RawConnection as y, type RuntimeAuthContext as z };