import type { CleanupRecord, NormalizedBleError } from '../backend-contract/errors.js'; import type { IpcClientIdentity, IpcClientLeaseIdentity, IpcEnvelope } from '../backend-contract/ipc.js'; import type { ConnectionState } from '../backend-contract/backend.js'; import type { ConnectionLifecycleCause } from '../backend-contract/connection-lifecycle.js'; import type { AttachmentId, IpcOperationCorrelation, IpcVersionAxes, IpcCompatibilityOffer, SerializableRecord } from '../backend-contract/primitives.js'; import type { AttachmentRecord } from '../backend-contract/identity.js'; import type { CapabilitySnapshot } from '../backend-contract/capabilities.js'; /** The one versioned request channel exposed by a host application's narrow preload bridge. */ export declare const IPC_BLE_PROTOCOL_CHANNEL = "unified-ble-manager:v2"; /** The version of the lifecycle value carried by the desktop webview v2 IPC stream. */ export declare const IPC_CONNECTION_LIFECYCLE_EVENT_SCHEMA_VERSION = 2; /** GATT database payload schema negotiated by the IPC protocol bootstrap. */ export declare const IPC_GATT_DATABASE_SCHEMA_VERSION = 2; /** Client-originated lifecycle stream identifiers occupy a reserved namespace. */ export declare const IPC_CONNECTION_EVENTS_STREAM_HANDLE_PREFIX = "connection-events-"; /** The IPC versions implemented by this package's desktop webview client. */ export declare const IPC_CLIENT_COMPATIBILITY_OFFER: IpcCompatibilityOffer; /** Validates the public client-originated lifecycle stream identifier format. */ export declare function isIpcConnectionEventsStreamHandle(value: string): boolean; /** Serializable attachment identity carried with a connection lifecycle event. */ export interface IpcAttachmentRecordV2 extends SerializableRecord { readonly attachmentId: string; readonly backendInstanceId: string; readonly backendGeneration: string; readonly adapter: IpcAdapterRecordV2; } export interface IpcAdapterRecordV2 extends SerializableRecord { readonly adapterId: string; readonly displayName: string | null; readonly state: IpcAdapterStateV2; readonly adapterGeneration: string; readonly limitations: readonly string[]; } export interface IpcAdapterStateV2 extends SerializableRecord { readonly availability: 'available' | 'unavailable' | 'unsupported' | 'unknown'; /** * `'unknown'` when the platform exposes no per-application Bluetooth * authorization concept at all, or when this host did not query one. It is * the absence of a measurement and never a denial: `'not-determined'` * asserts a pending user decision and `'unavailable'` asserts the platform * withheld access, so a host that did not measure reports `'unknown'`, * exactly as `availability` and `power` already do. `safeReason` states why. */ readonly authorization: 'granted' | 'denied' | 'restricted' | 'not-determined' | 'unavailable' | 'unknown'; readonly power: 'on' | 'off' | 'resetting' | 'unsupported' | 'unknown'; /** * Unsampled bootstrap snapshots are `null`. Live `adapter.state` is a * non-negative peripheral count from the host adapter. Absence of a * measurement is never `0`. */ readonly heard: number | null; readonly backendGeneration: string; readonly updatedAt: number; readonly safeReason: string | null; } export type IpcCapabilitySnapshotV2 = CapabilitySnapshot; /** Versioned, data-only projection of one public ConnectionLifecycleEvent. */ export interface IpcConnectionLifecycleEventV2 extends SerializableRecord { readonly kind: 'connection-lifecycle'; readonly schemaVersion: typeof IPC_CONNECTION_LIFECYCLE_EVENT_SCHEMA_VERSION; readonly attachment: IpcAttachmentRecordV2; readonly attachmentId: string; readonly peerId: string; readonly connectionId: string; readonly connectionGeneration: string; readonly ownerLeaseId: string; readonly sequence: number; readonly backendIngressOrdinal: number | null; readonly previous: ConnectionState; readonly current: ConnectionState; readonly cause: ConnectionLifecycleCause; } /** * Result of the first connection lifecycle admission phase. `handle` is the * client-generated opaque handle confirmed by the host; the host begins * forwarding only after the matching readiness command. */ export interface IpcConnectionEventsSubscribeResponseV2 extends SerializableRecord { readonly handle: string; readonly connectionId: string; readonly connectionGeneration: string; readonly eventSchemaVersion: typeof IPC_CONNECTION_LIFECYCLE_EVENT_SCHEMA_VERSION; } export interface IpcDiscoveryDescriptor extends SerializableRecord { readonly kind: 'continuous-scan' | 'system-chooser' | 'hybrid'; } /** Immutable bootstrap data issued by the host after it authenticates a client. */ export interface IpcClientBootstrap { readonly attachment: AttachmentRecord; readonly attachmentId: AttachmentId; readonly versions: IpcVersionAxes; readonly capabilities: IpcCapabilitySnapshotV2; /** Host-issued discovery model. Older native attachments may omit it; the client then derives it from capabilities. */ readonly discovery?: IpcDiscoveryDescriptor; readonly renderer: IpcClientIdentity; readonly rendererLease: IpcClientLeaseIdentity; } /** Host-to-client bounded stream item. The preload must forward this unchanged. */ export interface IpcBleEvent { /** Exact bootstrap lifetime that owns this event. */ readonly rendererLease: IpcClientLeaseIdentity; /** Host-issued opaque identifier acknowledged after the preload delivers this event. */ readonly eventId: string; readonly streamId: string; readonly item: SerializableRecord; } export interface IpcBootstrapRequest { readonly kind: 'bootstrap'; readonly offer: IpcCompatibilityOffer; } export declare function createIpcBootstrapRequest(): IpcBootstrapRequest; export interface IpcRouteRequest { readonly kind: 'route'; readonly envelope: IpcEnvelope; /** Local cancellation signal carried across nested host transports; never serialized on the wire. */ readonly signal?: AbortSignal | null; } export interface IpcReleaseRequest { readonly kind: 'release'; readonly rendererLease: IpcClientLeaseIdentity; } /** Acknowledges a host-to-client event after the preload has delivered it. */ export interface IpcEventAcknowledgeRequest { readonly kind: 'event.ack'; readonly rendererLease: IpcClientLeaseIdentity; readonly eventId: string; } export type IpcBleRequest = IpcBootstrapRequest | IpcRouteRequest | IpcReleaseRequest | IpcEventAcknowledgeRequest; export interface IpcBootstrapResponse { readonly kind: 'bootstrap'; readonly bootstrap: IpcClientBootstrap; } export interface IpcRouteResponse { readonly kind: 'route'; readonly payload: SerializableRecord; } export interface IpcReleaseResponse { readonly kind: 'release'; readonly cleanup: CleanupRecord; } export interface IpcEventAcknowledgeResponse { readonly kind: 'event.ack'; } /** Typed failure returned by the host-process IPC boundary; client code rehydrates it into a contract error. */ export interface IpcFailureResponse { readonly kind: 'failure'; readonly error: NormalizedBleError; } export type IpcBleSuccessResponse = IpcBootstrapResponse | IpcRouteResponse | IpcReleaseResponse | IpcEventAcknowledgeResponse; export type IpcBleResponse = IpcBleSuccessResponse | IpcFailureResponse; /** * Host-neutral client transport contract. It deliberately contains no Electron, * Tauri, Node, native-addon, or direct-radio import, so every desktop webview * host implements exactly these three operations. * * Event-sink lifecycle invariant, which every transport author must preserve: * * - The event sink is established exactly once, by the attach (`bootstrap`) * request, and remains valid for the lifetime of that attachment. `subscribe` * only adds and removes local listeners on that one already-established sink. * - `invoke` is strictly request/response. It must never carry, re-send, or * rebind the event sink, and neither a `route`, a `release`, nor an * `acknowledge` round trip may disturb event delivery. * - Re-attaching, meaning a further `bootstrap` request, is the only operation * that rebinds the sink. * * This is a correctness rule, not a style preference. Tauri deserializes every * `Channel` command argument into a *new* Rust `Channel` bound to the one * JavaScript callback id, and dropping any one of them evals * `{ end: true, index }` for that shared id. The Tauri JS runtime answers an end * message whose index matches its next expected index by calling * `unregisterCallback`, which tears the shared callback down permanently. A * transport that re-sent its sink on a later request would therefore let the * request/response path silently kill the event path: connection lifecycle, * advertisement, and notification streams stop with no rejection and no error * anywhere. Hosts whose sink is a long-lived listener registration carry the * same requirement for the same reason: one binding, one attachment lifetime. * * `executePublicIpcTransportScenario` in * `src/tck/runner-public-ipc-transport-scenario.ts` proves this invariant * against any implementation of this interface. */ export interface IpcClientTransport { invoke(request: IpcBleRequest): Promise>; subscribe(listener: (event: IpcBleEvent) => void): () => void; acknowledge(rendererLease: IpcClientLeaseIdentity, eventId: string): Promise; } export interface IpcOperationRequest { readonly command: string; readonly payload: SerializableRecord; readonly binaryPayload: Uint8Array | null; readonly signal: AbortSignal | null; } export interface IpcOperationReceipt { readonly correlation: IpcOperationCorrelation; readonly payload: SerializableRecord; } //# sourceMappingURL=protocol.d.ts.map