@ai-matrx/desktop-protocol 0.21.79 → 0.21.80
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/CHANGELOG.md +12 -1
- package/dist/client.cjs +45 -3
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +24 -0
- package/dist/client.d.ts +24 -0
- package/dist/client.js +45 -3
- package/dist/client.js.map +1 -1
- package/dist/react.d.cts +2 -0
- package/dist/react.d.ts +2 -0
- package/package.json +2 -2
package/dist/client.d.cts
CHANGED
|
@@ -70,6 +70,22 @@ type DesktopClientDiagnostic = {
|
|
|
70
70
|
} | {
|
|
71
71
|
kind: "heartbeat_timeout";
|
|
72
72
|
silentMs: number;
|
|
73
|
+
}
|
|
74
|
+
/** Every socket end, so a drop (1006: no close frame) can be matched to an edge event later. */
|
|
75
|
+
| {
|
|
76
|
+
kind: "socket_closed";
|
|
77
|
+
code: number | null;
|
|
78
|
+
reason: string;
|
|
79
|
+
wasClean: boolean;
|
|
80
|
+
idleSinceLastRxMs: number;
|
|
81
|
+
pongs: number;
|
|
82
|
+
}
|
|
83
|
+
/** A stream heard nothing (no meta, result, data or error) within its first-frame deadline. */
|
|
84
|
+
| {
|
|
85
|
+
kind: "first_frame_timeout";
|
|
86
|
+
id: string;
|
|
87
|
+
op: string;
|
|
88
|
+
waitedMs: number;
|
|
73
89
|
} | {
|
|
74
90
|
kind: "reconnect_alarm";
|
|
75
91
|
attempts: number;
|
|
@@ -110,6 +126,12 @@ interface DesktopClientOptions {
|
|
|
110
126
|
heartbeatMs?: number;
|
|
111
127
|
/** Unary request timeout. Default 70 000 (the relay's call default). */
|
|
112
128
|
requestTimeoutMs?: number;
|
|
129
|
+
/**
|
|
130
|
+
* A stream request that hears nothing back (no meta, result, data or error) within this many ms
|
|
131
|
+
* ends with a retryable TIMEOUT, and the socket is probed (reconnecting if it is dead). A stream
|
|
132
|
+
* never waits without a deadline. Default: requestTimeoutMs.
|
|
133
|
+
*/
|
|
134
|
+
firstFrameMs?: number;
|
|
113
135
|
/** Fresh access token for `relay.reauth` when the relay sends `relay.auth_expiring`. */
|
|
114
136
|
getToken?: () => Promise<string>;
|
|
115
137
|
/** Background problems — loud by contract; default logs to console.warn. */
|
|
@@ -146,6 +168,8 @@ interface StreamOptions extends RequestOptions {
|
|
|
146
168
|
windowBytes?: number;
|
|
147
169
|
/** Reattach mode for resource streams. Default "control". */
|
|
148
170
|
mode?: "control" | "read_only";
|
|
171
|
+
/** This stream's first-frame deadline (overrides the client's firstFrameMs). */
|
|
172
|
+
firstFrameMs?: number;
|
|
149
173
|
}
|
|
150
174
|
interface DesktopStream<N extends StreamOpName> {
|
|
151
175
|
/** The CURRENT request id carrying this stream (changes on reattach). */
|
package/dist/client.d.ts
CHANGED
|
@@ -70,6 +70,22 @@ type DesktopClientDiagnostic = {
|
|
|
70
70
|
} | {
|
|
71
71
|
kind: "heartbeat_timeout";
|
|
72
72
|
silentMs: number;
|
|
73
|
+
}
|
|
74
|
+
/** Every socket end, so a drop (1006: no close frame) can be matched to an edge event later. */
|
|
75
|
+
| {
|
|
76
|
+
kind: "socket_closed";
|
|
77
|
+
code: number | null;
|
|
78
|
+
reason: string;
|
|
79
|
+
wasClean: boolean;
|
|
80
|
+
idleSinceLastRxMs: number;
|
|
81
|
+
pongs: number;
|
|
82
|
+
}
|
|
83
|
+
/** A stream heard nothing (no meta, result, data or error) within its first-frame deadline. */
|
|
84
|
+
| {
|
|
85
|
+
kind: "first_frame_timeout";
|
|
86
|
+
id: string;
|
|
87
|
+
op: string;
|
|
88
|
+
waitedMs: number;
|
|
73
89
|
} | {
|
|
74
90
|
kind: "reconnect_alarm";
|
|
75
91
|
attempts: number;
|
|
@@ -110,6 +126,12 @@ interface DesktopClientOptions {
|
|
|
110
126
|
heartbeatMs?: number;
|
|
111
127
|
/** Unary request timeout. Default 70 000 (the relay's call default). */
|
|
112
128
|
requestTimeoutMs?: number;
|
|
129
|
+
/**
|
|
130
|
+
* A stream request that hears nothing back (no meta, result, data or error) within this many ms
|
|
131
|
+
* ends with a retryable TIMEOUT, and the socket is probed (reconnecting if it is dead). A stream
|
|
132
|
+
* never waits without a deadline. Default: requestTimeoutMs.
|
|
133
|
+
*/
|
|
134
|
+
firstFrameMs?: number;
|
|
113
135
|
/** Fresh access token for `relay.reauth` when the relay sends `relay.auth_expiring`. */
|
|
114
136
|
getToken?: () => Promise<string>;
|
|
115
137
|
/** Background problems — loud by contract; default logs to console.warn. */
|
|
@@ -146,6 +168,8 @@ interface StreamOptions extends RequestOptions {
|
|
|
146
168
|
windowBytes?: number;
|
|
147
169
|
/** Reattach mode for resource streams. Default "control". */
|
|
148
170
|
mode?: "control" | "read_only";
|
|
171
|
+
/** This stream's first-frame deadline (overrides the client's firstFrameMs). */
|
|
172
|
+
firstFrameMs?: number;
|
|
149
173
|
}
|
|
150
174
|
interface DesktopStream<N extends StreamOpName> {
|
|
151
175
|
/** The CURRENT request id carrying this stream (changes on reattach). */
|
package/dist/client.js
CHANGED
|
@@ -56,6 +56,7 @@ function createDesktopClient(options) {
|
|
|
56
56
|
const makeSocket = options.webSocket ?? defaultWebSocket();
|
|
57
57
|
const heartbeatMs = options.heartbeatMs ?? 25e3;
|
|
58
58
|
const requestTimeoutMs = options.requestTimeoutMs ?? 7e4;
|
|
59
|
+
const firstFrameMs = options.firstFrameMs ?? requestTimeoutMs;
|
|
59
60
|
const protocolVersion = options.protocolVersion ?? `${PROTOCOL_MAJOR}.${PROTOCOL_MINOR}`;
|
|
60
61
|
const backoff = createBackoff({ ...options.backoff, now: timers.now });
|
|
61
62
|
const diagnose = options.onDiagnostic ?? ((d) => {
|
|
@@ -93,6 +94,7 @@ function createDesktopClient(options) {
|
|
|
93
94
|
let probeTimer = null;
|
|
94
95
|
let lastHeardAt = 0;
|
|
95
96
|
let heardCount = 0;
|
|
97
|
+
let pongs = 0;
|
|
96
98
|
let closedByUser = false;
|
|
97
99
|
const newId = (prefix) => `${prefix}${(++nextId).toString(36)}`;
|
|
98
100
|
function setState(patch) {
|
|
@@ -140,6 +142,7 @@ function createDesktopClient(options) {
|
|
|
140
142
|
ws.onopen = () => {
|
|
141
143
|
if (generation !== socketGeneration) return;
|
|
142
144
|
lastHeardAt = timers.now();
|
|
145
|
+
pongs = 0;
|
|
143
146
|
helloId = newId("h");
|
|
144
147
|
setState({ status: "handshaking" });
|
|
145
148
|
sendJson({ type: "hello", id: helloId, protocolVersion, clientType: options.clientType, clientVersion: options.clientVersion });
|
|
@@ -155,6 +158,8 @@ function createDesktopClient(options) {
|
|
|
155
158
|
};
|
|
156
159
|
ws.onclose = (event) => {
|
|
157
160
|
if (generation !== socketGeneration) return;
|
|
161
|
+
const ev = event;
|
|
162
|
+
reportClose(ev.code, ev.reason ?? "", ev.wasClean ?? false);
|
|
158
163
|
onSocketGone(generation, event.code, null);
|
|
159
164
|
};
|
|
160
165
|
}
|
|
@@ -166,6 +171,7 @@ function createDesktopClient(options) {
|
|
|
166
171
|
const silentMs = timers.now() - lastHeardAt;
|
|
167
172
|
if (silentMs >= heartbeatMs * 2) {
|
|
168
173
|
diagnose({ kind: "heartbeat_timeout", silentMs });
|
|
174
|
+
reportClose(null, "heartbeat timeout", false);
|
|
169
175
|
const dead = socket;
|
|
170
176
|
onSocketGone(generation, null, new DesktopProtocolError("TIMEOUT", "Connection went silent", { retryable: true }));
|
|
171
177
|
try {
|
|
@@ -178,6 +184,9 @@ function createDesktopClient(options) {
|
|
|
178
184
|
scheduleHeartbeat(generation);
|
|
179
185
|
}, heartbeatMs);
|
|
180
186
|
}
|
|
187
|
+
function reportClose(code, reason, wasClean) {
|
|
188
|
+
diagnose({ kind: "socket_closed", code, reason: reason.slice(0, 120), wasClean, idleSinceLastRxMs: Math.max(0, timers.now() - lastHeardAt), pongs });
|
|
189
|
+
}
|
|
181
190
|
function onSocketGone(generation, code, error) {
|
|
182
191
|
if (generation !== socketGeneration) return;
|
|
183
192
|
socketGeneration++;
|
|
@@ -266,7 +275,10 @@ function createDesktopClient(options) {
|
|
|
266
275
|
}
|
|
267
276
|
function onMessage(data) {
|
|
268
277
|
if (typeof data === "string") {
|
|
269
|
-
if (data === PONG_TEXT)
|
|
278
|
+
if (data === PONG_TEXT) {
|
|
279
|
+
pongs++;
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
270
282
|
let json;
|
|
271
283
|
try {
|
|
272
284
|
json = JSON.parse(data);
|
|
@@ -297,6 +309,10 @@ function createDesktopClient(options) {
|
|
|
297
309
|
onFrame(frame.header, frame.payload);
|
|
298
310
|
}
|
|
299
311
|
function onEnvelope(msg) {
|
|
312
|
+
if (msg.type !== "event") {
|
|
313
|
+
const heard = streams.get(msg.id);
|
|
314
|
+
if (heard) clearFirstFrame(heard);
|
|
315
|
+
}
|
|
300
316
|
switch (msg.type) {
|
|
301
317
|
case "response": {
|
|
302
318
|
if (msg.id === helloId) return onWelcome(msg.result);
|
|
@@ -438,6 +454,7 @@ function createDesktopClient(options) {
|
|
|
438
454
|
diagnose({ kind: "unknown_stream", sid: header.sid });
|
|
439
455
|
return;
|
|
440
456
|
}
|
|
457
|
+
clearFirstFrame(s);
|
|
441
458
|
const isData = header.channel === FrameChannel.DATA || header.channel === FrameChannel.STDERR;
|
|
442
459
|
const isSnapshot = header.channel === FrameChannel.SNAPSHOT;
|
|
443
460
|
if (!isData && !isSnapshot) {
|
|
@@ -483,8 +500,29 @@ function createDesktopClient(options) {
|
|
|
483
500
|
socket.send(encodeFrame({ version: FRAME_VERSION, flags: 0, channel: FrameChannel.STDIN, cid: 0, sid: s.sid, seq: s.sendSeq }, chunk));
|
|
484
501
|
}
|
|
485
502
|
}
|
|
503
|
+
function clearFirstFrame(s) {
|
|
504
|
+
if (s.firstFrameTimer === null) return;
|
|
505
|
+
timers.clearTimeout(s.firstFrameTimer);
|
|
506
|
+
s.firstFrameTimer = null;
|
|
507
|
+
}
|
|
508
|
+
function armFirstFrame(s) {
|
|
509
|
+
clearFirstFrame(s);
|
|
510
|
+
const waitMs = s.options.firstFrameMs ?? firstFrameMs;
|
|
511
|
+
const id = s.id;
|
|
512
|
+
s.firstFrameTimer = timers.setTimeout(() => {
|
|
513
|
+
s.firstFrameTimer = null;
|
|
514
|
+
if (s.ended || s.id !== id) return;
|
|
515
|
+
diagnose({ kind: "first_frame_timeout", id, op: s.op, waitedMs: waitMs });
|
|
516
|
+
streams.delete(id);
|
|
517
|
+
if (s.sid !== null) bySid.delete(s.sid);
|
|
518
|
+
abandon(id);
|
|
519
|
+
endStream(s, null, new DesktopProtocolError("TIMEOUT", `${s.op}: no answer within ${waitMs} ms`, { retryable: true }));
|
|
520
|
+
wake();
|
|
521
|
+
}, waitMs);
|
|
522
|
+
}
|
|
486
523
|
function endStream(s, reason, error) {
|
|
487
524
|
if (s.ended) return;
|
|
525
|
+
clearFirstFrame(s);
|
|
488
526
|
s.ended = true;
|
|
489
527
|
s.sendQueue = [];
|
|
490
528
|
if (!s.resultSettled) {
|
|
@@ -507,7 +545,7 @@ function createDesktopClient(options) {
|
|
|
507
545
|
const params = { resource_id: s.resourceId, mode: s.options.mode ?? "control" };
|
|
508
546
|
if (s.lastSeq > 0) params.since_seq = s.lastSeq;
|
|
509
547
|
if (s.options.windowBytes !== void 0) params.window_bytes = s.options.windowBytes;
|
|
510
|
-
sendJson({ id, type: "request", cap: "session", op: "attach", params });
|
|
548
|
+
if (sendJson({ id, type: "request", cap: "session", op: "attach", params })) armFirstFrame(s);
|
|
511
549
|
}
|
|
512
550
|
function safeCall(where, fn) {
|
|
513
551
|
try {
|
|
@@ -616,7 +654,8 @@ function createDesktopClient(options) {
|
|
|
616
654
|
resolveDone,
|
|
617
655
|
rejectDone,
|
|
618
656
|
ended: false,
|
|
619
|
-
reattaching: false
|
|
657
|
+
reattaching: false,
|
|
658
|
+
firstFrameTimer: null
|
|
620
659
|
};
|
|
621
660
|
const start = async () => {
|
|
622
661
|
let welcome;
|
|
@@ -635,7 +674,9 @@ function createDesktopClient(options) {
|
|
|
635
674
|
if (!sendJson({ id: s.id, type: "request", ...capOf(op), params: wire })) {
|
|
636
675
|
streams.delete(s.id);
|
|
637
676
|
endStream(s, null, new DesktopProtocolError("DEVICE_OFFLINE", "Connection lost", { retryable: true }));
|
|
677
|
+
return;
|
|
638
678
|
}
|
|
679
|
+
armFirstFrame(s);
|
|
639
680
|
};
|
|
640
681
|
void start();
|
|
641
682
|
opts.signal?.addEventListener("abort", () => handle.cancel(), { once: true });
|
|
@@ -711,6 +752,7 @@ function createDesktopClient(options) {
|
|
|
711
752
|
if (heardCount > heardBefore) return;
|
|
712
753
|
const silentMs = timers.now() - lastHeardAt;
|
|
713
754
|
diagnose({ kind: "heartbeat_timeout", silentMs });
|
|
755
|
+
reportClose(null, "wake probe timeout", false);
|
|
714
756
|
const dead = socket;
|
|
715
757
|
onSocketGone(generation, null, new DesktopProtocolError("TIMEOUT", "Connection went silent", { retryable: true }));
|
|
716
758
|
try {
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/client/client.ts","../src/client/wake.ts","../src/client/transcribe.ts"],"sourcesContent":["/**\n * The reconnecting desktop-protocol client: hello → requests, streams with credit-based\n * backpressure, events, transparent reattach of resource streams (terminals, watches) after a\n * drop, heartbeat, and relay reauth. One instance per device connection. All state lives in the\n * closure — no module-level state (dual ESM/CJS graphs would split it).\n */\nimport { RECONNECT_ALARM_ATTEMPTS, createBackoff } from \"@ai-matrx/data/realtime\";\nimport { DesktopProtocolError } from \"../error\";\nimport { FRAME_VERSION, FrameChannel, decodeFrame, encodeFrame } from \"../frame\";\nimport type { FrameHeader } from \"../frame\";\nimport { closeRule } from \"../close-policy\";\nimport { CloseCode, CoreToClientMsg, PING_TEXT, PONG_TEXT, Welcome } from \"../schema/envelope\";\nimport type { EndReason, StreamMeta } from \"../schema/envelope\";\nimport type { ProtocolErrorBody } from \"../schema/errors\";\nimport { DEFAULT_MAX_FRAME_PAYLOAD_BYTES, DEFAULT_WINDOW_BYTES } from \"../schema/frame\";\nimport { PROTOCOL_MAJOR, PROTOCOL_MINOR } from \"../schema/primitives\";\nimport { EVENTS, OPS } from \"../schema/registry\";\nimport { knows } from \"../versioning\";\nimport type { OpName, OpParams, OpResult } from \"../schema/registry\";\nimport type {\n ClientTimers,\n DesktopClient,\n DesktopClientDiagnostic,\n DesktopClientOptions,\n DesktopClientState,\n DesktopStream,\n EventHandler,\n EventName,\n RequestOptions,\n StreamHandlers,\n StreamOpName,\n StreamOptions,\n WakeOptions,\n WebSocketFactory,\n WebSocketLike,\n} from \"./types\";\n\nconst WS_OPEN = 1;\ntype Pending = {\n kind: \"unary\";\n op: string;\n resolve: (value: unknown) => void;\n reject: (error: DesktopProtocolError) => void;\n cleanup: () => void;\n};\n\ninterface StreamState {\n op: string;\n handlers: StreamHandlers;\n options: StreamOptions;\n id: string;\n sid: number | null;\n resourceId: string | null;\n /** Last inbound DATA seq delivered to the consumer. */\n lastSeq: number;\n /** Expected next inbound seq, or null right after a gap/snapshot (resync on next frame). */\n expectSeq: number | null;\n windowBytes: number;\n /** Consumed bytes not yet credited back. */\n consumedUncredited: number;\n /** Outbound (STDIN) credit granted by the core. */\n sendWindow: number;\n sendSeq: number;\n sendQueue: Uint8Array[];\n /** Serializes consumer callbacks so credits follow consumption order. */\n chain: Promise<void>;\n resultSettled: boolean;\n resolveResult: (value: unknown) => void;\n rejectResult: (error: DesktopProtocolError) => void;\n resolveDone: (reason: EndReason) => void;\n rejectDone: (error: DesktopProtocolError) => void;\n ended: boolean;\n /** True while a reattach request is in flight for it. */\n reattaching: boolean;\n}\n\nconst defaultTimers: ClientTimers = {\n setTimeout: (fn, ms) => globalThis.setTimeout(fn, ms),\n clearTimeout: (handle) => globalThis.clearTimeout(handle as ReturnType<typeof globalThis.setTimeout>),\n now: () => Date.now(),\n};\n\nfunction defaultWebSocket(): WebSocketFactory {\n return (url, protocols) => {\n const Ctor = (globalThis as { WebSocket?: new (url: string, protocols?: string[]) => WebSocketLike }).WebSocket;\n if (!Ctor) {\n throw new DesktopProtocolError(\"PLATFORM_UNSUPPORTED\", \"No global WebSocket — pass options.webSocket\");\n }\n return new Ctor(url, protocols);\n };\n}\n\nfunction capOf(op: string): { cap: string; op: string } {\n const dot = op.indexOf(\".\");\n return { cap: op.slice(0, dot), op: op.slice(dot + 1) };\n}\n\nfunction fromBody(body: ProtocolErrorBody): DesktopProtocolError {\n return body.data === undefined\n ? new DesktopProtocolError(body.code, body.message, { retryable: body.retryable })\n : new DesktopProtocolError(body.code, body.message, { retryable: body.retryable, data: body.data });\n}\n\nfunction toBytes(data: unknown): Uint8Array | null {\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return null;\n}\n\nexport function createDesktopClient(options: DesktopClientOptions): DesktopClient {\n const timers = options.timers ?? defaultTimers;\n const makeSocket = options.webSocket ?? defaultWebSocket();\n const heartbeatMs = options.heartbeatMs ?? 25_000;\n const requestTimeoutMs = options.requestTimeoutMs ?? 70_000;\n const protocolVersion = options.protocolVersion ?? `${PROTOCOL_MAJOR}.${PROTOCOL_MINOR}`;\n const backoff = createBackoff({ ...options.backoff, now: timers.now });\n const diagnose =\n options.onDiagnostic ??\n ((d: DesktopClientDiagnostic) => {\n console.warn(\"[desktop-protocol]\", d.kind, d);\n });\n\n let state: DesktopClientState = {\n status: \"idle\",\n welcome: null,\n attempts: 0,\n retryInMs: null,\n lastError: null,\n lastCloseCode: null,\n outcome: null,\n };\n /** Token refusals (4001/4008) since the last welcome; the second in a row is terminal. */\n let authRefusals = 0;\n const listeners = new Set<() => void>();\n const readyWaiters = new Set<{ resolve: (w: Welcome) => void; reject: (e: DesktopProtocolError) => void }>();\n const pending = new Map<string, Pending>();\n // Requests this client gave up on (aborted or timed out) after telling the core \"cancel\". The\n // core still answers each one exactly once — CANCELLED, or the result if it finished first — so\n // that one answer is expected and consumed here, not reported as unknown_request. Bounded: an\n // answer that never comes cannot grow it past ABANDONED_MAX; a dropped socket clears it.\n const abandoned = new Set<string>();\n const ABANDONED_MAX = 1024;\n function abandon(id: string): void {\n if (!sendJson({ id, type: \"cancel\" })) return;\n abandoned.add(id);\n if (abandoned.size > ABANDONED_MAX) abandoned.delete(abandoned.values().next().value as string);\n }\n const streams = new Map<string, StreamState>(); // by current request id\n const bySid = new Map<number, StreamState>();\n const eventHandlers = new Map<string, Set<EventHandler<EventName>>>();\n let socket: WebSocketLike | null = null;\n let socketGeneration = 0;\n let nextId = 0;\n let helloId: string | null = null;\n let reconnectTimer: unknown = null;\n let heartbeatTimer: unknown = null;\n let probeTimer: unknown = null;\n let lastHeardAt = 0;\n /** Inbound messages on the current socket — the wake probe's \"was anything heard since?\" */\n let heardCount = 0;\n let closedByUser = false;\n\n const newId = (prefix: string) => `${prefix}${(++nextId).toString(36)}`;\n\n function setState(patch: Partial<DesktopClientState>): void {\n state = { ...state, ...patch };\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n diagnose({ kind: \"handler_threw\", where: \"subscribe listener\", error });\n }\n }\n }\n\n function sendJson(message: unknown): boolean {\n if (!socket || socket.readyState !== WS_OPEN) return false;\n socket.send(JSON.stringify(message));\n return true;\n }\n\n // ── connection lifecycle ────────────────────────────────────────────────────\n\n function connect(): void {\n if (state.status === \"connecting\" || state.status === \"handshaking\" || state.status === \"open\") return;\n if (state.status === \"closed\" || state.status === \"idle\") authRefusals = 0; // a deliberate (re)start\n closedByUser = false;\n if (reconnectTimer !== null) {\n timers.clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n void openSocket();\n }\n\n async function openSocket(): Promise<void> {\n const generation = ++socketGeneration;\n setState({ status: \"connecting\", retryInMs: null });\n let ws: WebSocketLike;\n try {\n const url = typeof options.url === \"function\" ? await options.url() : options.url;\n const protocols = options.protocols ? await options.protocols() : [];\n if (generation !== socketGeneration || closedByUser) return;\n ws = makeSocket(url, protocols);\n } catch (error) {\n if (generation !== socketGeneration) return;\n const err =\n error instanceof DesktopProtocolError\n ? error\n : new DesktopProtocolError(\"INTERNAL\", \"Could not open the connection\", { retryable: true, cause: error });\n onSocketGone(generation, null, err);\n return;\n }\n socket = ws;\n ws.binaryType = \"arraybuffer\";\n ws.onopen = () => {\n if (generation !== socketGeneration) return;\n lastHeardAt = timers.now();\n helloId = newId(\"h\");\n setState({ status: \"handshaking\" });\n sendJson({ type: \"hello\", id: helloId, protocolVersion, clientType: options.clientType, clientVersion: options.clientVersion });\n scheduleHeartbeat(generation);\n };\n ws.onmessage = (event) => {\n if (generation !== socketGeneration) return;\n lastHeardAt = timers.now();\n heardCount++;\n onMessage(event.data);\n };\n ws.onerror = () => {\n // The close event that always follows carries the code; nothing to do here.\n };\n ws.onclose = (event) => {\n if (generation !== socketGeneration) return;\n onSocketGone(generation, event.code, null);\n };\n }\n\n function scheduleHeartbeat(generation: number): void {\n if (heartbeatTimer !== null) timers.clearTimeout(heartbeatTimer);\n heartbeatTimer = timers.setTimeout(() => {\n heartbeatTimer = null;\n if (generation !== socketGeneration || !socket) return;\n const silentMs = timers.now() - lastHeardAt;\n if (silentMs >= heartbeatMs * 2) {\n diagnose({ kind: \"heartbeat_timeout\", silentMs });\n const dead = socket;\n onSocketGone(generation, null, new DesktopProtocolError(\"TIMEOUT\", \"Connection went silent\", { retryable: true }));\n try {\n dead.close(CloseCode.NORMAL, \"heartbeat timeout\");\n } catch {\n // already closing\n }\n return;\n }\n if (socket.readyState === WS_OPEN) socket.send(PING_TEXT);\n scheduleHeartbeat(generation);\n }, heartbeatMs);\n }\n\n /** The socket is gone (close event, open failure or heartbeat death). */\n function onSocketGone(generation: number, code: number | null, error: DesktopProtocolError | null): void {\n if (generation !== socketGeneration) return;\n socketGeneration++; // ignore anything the dead socket still emits\n if (socket) {\n socket.onopen = socket.onmessage = socket.onclose = socket.onerror = null;\n }\n socket = null;\n helloId = null;\n if (heartbeatTimer !== null) {\n timers.clearTimeout(heartbeatTimer);\n heartbeatTimer = null;\n }\n if (probeTimer !== null) {\n timers.clearTimeout(probeTimer);\n probeTimer = null;\n }\n // The one close table (close-policy.ts) decides: retry, retry with a fresh token, or stop.\n const rule = code === null ? null : closeRule(code);\n if (rule?.action === \"reauth\") authRefusals++;\n const stopped = rule !== null && (rule.action === \"stop\" || (rule.action === \"reauth\" && authRefusals >= 2));\n const terminal = stopped && rule ? rule : undefined;\n const lost =\n error ??\n (terminal\n ? new DesktopProtocolError(terminal.error[0], terminal.error[1])\n : rule && rule.action === \"reauth\"\n ? new DesktopProtocolError(rule.error[0], rule.error[1], { retryable: true })\n : new DesktopProtocolError(\"DEVICE_OFFLINE\", \"Connection lost\", { retryable: true }));\n\n // Unary requests cannot survive a drop: the caller decides whether to retry.\n abandoned.clear();\n for (const [id, p] of pending) {\n pending.delete(id);\n p.cleanup();\n p.reject(lost);\n }\n // Resource streams survive (reattach on reconnect); everything else ends now.\n bySid.clear();\n for (const [id, s] of streams) {\n if (s.resourceId !== null && terminal === undefined && !closedByUser) {\n s.sid = null;\n s.reattaching = false;\n continue;\n }\n streams.delete(id);\n endStream(s, null, lost);\n }\n\n if (closedByUser || terminal) {\n setState({\n status: \"closed\",\n welcome: null,\n lastError: closedByUser ? state.lastError : lost,\n lastCloseCode: code,\n retryInMs: null,\n outcome: closedByUser ? null : (terminal?.outcome ?? null),\n });\n rejectReadyWaiters(lost);\n return;\n }\n const delay = backoff.nextDelayMs();\n if (backoff.isAlarming()) diagnose({ kind: \"reconnect_alarm\", attempts: backoff.attempts() });\n setState({ status: \"reconnecting\", welcome: null, attempts: backoff.attempts(), retryInMs: delay, lastError: lost, lastCloseCode: code });\n reconnectTimer = timers.setTimeout(() => {\n reconnectTimer = null;\n if (!closedByUser) void openSocket();\n }, delay);\n }\n\n function rejectReadyWaiters(error: DesktopProtocolError): void {\n for (const w of [...readyWaiters]) {\n readyWaiters.delete(w);\n w.reject(error);\n }\n }\n\n function close(): void {\n closedByUser = true;\n if (reconnectTimer !== null) {\n timers.clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n const cancelled = new DesktopProtocolError(\"CANCELLED\", \"Client closed\");\n const ws = socket;\n if (ws) {\n onSocketGone(socketGeneration, CloseCode.NORMAL, cancelled);\n try {\n ws.close(CloseCode.NORMAL, \"client closed\");\n } catch {\n // already closed\n }\n } else {\n for (const [id, s] of streams) {\n streams.delete(id);\n endStream(s, null, cancelled);\n }\n setState({ status: \"closed\", retryInMs: null });\n rejectReadyWaiters(cancelled);\n }\n }\n\n // ── inbound ────────────────────────────────────────────────────────────────\n\n function onMessage(data: unknown): void {\n if (typeof data === \"string\") {\n if (data === PONG_TEXT) return;\n let json: unknown;\n try {\n json = JSON.parse(data);\n } catch {\n diagnose({ kind: \"malformed_message\", detail: \"not JSON\" });\n return;\n }\n const parsed = CoreToClientMsg.safeParse(json);\n if (!parsed.success) {\n diagnose({ kind: \"malformed_message\", detail: parsed.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \") });\n return;\n }\n onEnvelope(parsed.data);\n return;\n }\n const bytes = toBytes(data);\n if (bytes === null) {\n diagnose({ kind: \"malformed_message\", detail: \"binary message is not an ArrayBuffer/view (set binaryType)\" });\n return;\n }\n let frame: ReturnType<typeof decodeFrame>;\n try {\n frame = decodeFrame(bytes);\n } catch (error) {\n diagnose({ kind: \"malformed_message\", detail: error instanceof Error ? error.message : String(error) });\n return;\n }\n onFrame(frame.header, frame.payload);\n }\n\n function onEnvelope(msg: CoreToClientMsg): void {\n switch (msg.type) {\n case \"response\": {\n if (msg.id === helloId) return onWelcome(msg.result);\n const s = streams.get(msg.id);\n if (s) return onStreamResult(s, msg.result);\n const p = pending.get(msg.id);\n if (!p) {\n if (abandoned.delete(msg.id)) return; // the one answer to a request we cancelled\n return diagnose({ kind: \"unknown_request\", id: msg.id, type: msg.type });\n }\n pending.delete(msg.id);\n p.cleanup();\n p.resolve(msg.result);\n return;\n }\n case \"error\": {\n const error = fromBody(msg.error);\n if (msg.id === helloId) return onHelloRefused(error);\n const s = streams.get(msg.id);\n if (s) {\n if (s.reattaching && s.resourceId !== null) diagnose({ kind: \"reattach_failed\", resourceId: s.resourceId, error });\n streams.delete(msg.id);\n if (s.sid !== null) bySid.delete(s.sid);\n return endStream(s, null, error);\n }\n const p = pending.get(msg.id);\n if (!p) {\n if (abandoned.delete(msg.id)) return; // the one answer to a request we cancelled\n return diagnose({ kind: \"unknown_request\", id: msg.id, type: msg.type });\n }\n pending.delete(msg.id);\n p.cleanup();\n p.reject(error);\n return;\n }\n case \"stream\": {\n const s = streams.get(msg.id);\n if (!s) return diagnose({ kind: \"unknown_request\", id: msg.id, type: msg.type });\n onStreamMeta(s, msg.meta);\n return;\n }\n case \"end\": {\n const s = streams.get(msg.id);\n if (!s) return diagnose({ kind: \"unknown_request\", id: msg.id, type: msg.type });\n // Deliver everything already queued before announcing the end.\n void s.chain.then(() => {\n streams.delete(s.id);\n if (s.sid !== null) bySid.delete(s.sid);\n endStream(s, msg.reason ?? \"completed\", null);\n });\n return;\n }\n case \"credit\": {\n const s = streams.get(msg.id);\n if (!s) return diagnose({ kind: \"unknown_request\", id: msg.id, type: msg.type });\n s.sendWindow += msg.n;\n flushSend(s);\n return;\n }\n case \"event\": {\n const key = `${msg.cap}.${msg.name}`;\n const schema = (EVENTS as Record<string, (typeof EVENTS)[EventName]>)[key];\n if (!schema) return diagnose({ kind: \"malformed_message\", detail: `unknown event ${key}` });\n const payload = schema.safeParse(msg.payload);\n if (!payload.success) return diagnose({ kind: \"malformed_message\", detail: `event ${key}: invalid payload` });\n if (key === \"relay.auth_expiring\" && options.getToken) {\n options.getToken().then(reauth, (error: unknown) => diagnose({ kind: \"reauth_failed\", error }));\n }\n for (const handler of [...(eventHandlers.get(key) ?? [])]) {\n try {\n handler(payload.data as never, msg.resourceId);\n } catch (error) {\n diagnose({ kind: \"handler_threw\", where: `event ${key}`, error });\n }\n }\n return;\n }\n }\n }\n\n function onWelcome(result: unknown): void {\n const welcome = Welcome.safeParse(result);\n if (!welcome.success) {\n onHelloRefused(new DesktopProtocolError(\"PROTOCOL_ERROR\", \"Malformed welcome\"));\n return;\n }\n helloId = null;\n backoff.markConnected();\n authRefusals = 0;\n setState({ status: \"open\", welcome: welcome.data, attempts: 0, retryInMs: null, lastError: null, outcome: null });\n // 1.38: say what this client is (\"iPhone\"), first on the wire, so \"Started from iPhone\" is the\n // core's own stamp. Never to an older core (a hello field would have made it refuse the hello).\n if (options.clientLabel && knows(welcome.data.protocol_version, \"1.38\")) {\n void request(\"session.identify\", { label: options.clientLabel.slice(0, 60) }).catch((error: unknown) =>\n diagnose({ kind: \"handler_threw\", where: \"session.identify\", error }),\n );\n }\n for (const w of [...readyWaiters]) {\n readyWaiters.delete(w);\n w.resolve(welcome.data);\n }\n // Transparent reattach: every surviving resource stream continues where its consumer stopped.\n for (const s of [...streams.values()]) {\n if (s.sid === null && s.resourceId !== null && !s.ended) reattach(s, welcome.data);\n }\n }\n\n function onHelloRefused(error: DesktopProtocolError): void {\n // An unsupported version will not fix itself on retry: UPGRADE_REQUIRED is a terminal close.\n const ws = socket;\n onSocketGone(socketGeneration, error.code === \"PROTOCOL_VERSION_UNSUPPORTED\" ? CloseCode.UPGRADE_REQUIRED : null, error);\n try {\n ws?.close(CloseCode.NORMAL, \"hello refused\");\n } catch {\n // already closed\n }\n }\n\n // ── streams ────────────────────────────────────────────────────────────────\n\n function onStreamResult(s: StreamState, result: unknown): void {\n if (s.reattaching) {\n // session.attach result = ResourceInfo; the stream continues on the new id.\n s.reattaching = false;\n safeCall(\"onReattached\", () => s.handlers.onReattached?.());\n return;\n }\n const rid = (result as { resource_id?: unknown } | null)?.resource_id;\n if (typeof rid === \"string\") s.resourceId = rid;\n if (!s.resultSettled) {\n s.resultSettled = true;\n s.resolveResult(result);\n }\n }\n\n function onStreamMeta(s: StreamState, meta: StreamMeta): void {\n if (meta.kind === \"open\") {\n if (s.sid !== null) bySid.delete(s.sid);\n s.sid = meta.sid;\n s.windowBytes = meta.window_bytes;\n if (meta.resource_id !== undefined) s.resourceId = meta.resource_id;\n bySid.set(meta.sid, s);\n flushSend(s);\n } else {\n // gap or snapshot: the next DATA frame re-establishes the sequence.\n s.expectSeq = null;\n }\n safeCall(\"onMeta\", () => s.handlers.onMeta?.(meta));\n }\n\n function onFrame(header: FrameHeader, payload: Uint8Array): void {\n const s = bySid.get(header.sid);\n if (!s) {\n diagnose({ kind: \"unknown_stream\", sid: header.sid });\n return;\n }\n const isData = header.channel === FrameChannel.DATA || header.channel === FrameChannel.STDERR;\n const isSnapshot = header.channel === FrameChannel.SNAPSHOT;\n if (!isData && !isSnapshot) {\n diagnose({ kind: \"malformed_message\", detail: `channel ${header.channel} is not client-bound` });\n return;\n }\n if (isData) {\n if (s.expectSeq !== null && header.seq !== s.expectSeq) {\n diagnose({ kind: \"seq_gap\", id: s.id, expected: s.expectSeq, received: header.seq });\n }\n s.expectSeq = header.seq + 1;\n }\n // Copy: the payload is a view into a buffer the transport may reuse.\n const bytes = payload.slice();\n const handler = isData ? s.handlers.onData : s.handlers.onSnapshot;\n s.chain = s.chain.then(async () => {\n if (s.ended) return;\n try {\n await handler?.(bytes, header);\n } catch (error) {\n diagnose({ kind: \"handler_threw\", where: isData ? \"onData\" : \"onSnapshot\", error });\n }\n if (isData) s.lastSeq = header.seq;\n grantCredit(s, bytes.byteLength);\n });\n }\n\n function grantCredit(s: StreamState, consumed: number): void {\n s.consumedUncredited += consumed;\n // Batch: one credit per quarter window keeps the pipe full without a message per frame.\n if (s.consumedUncredited >= Math.max(1, Math.floor(s.windowBytes / 4))) {\n if (sendJson({ type: \"credit\", id: s.id, n: s.consumedUncredited })) s.consumedUncredited = 0;\n }\n }\n\n function flushSend(s: StreamState): void {\n if (s.sid === null || !socket || socket.readyState !== WS_OPEN) return;\n const maxPayload = state.welcome?.limits.max_frame_payload_bytes ?? DEFAULT_MAX_FRAME_PAYLOAD_BYTES;\n while (s.sendQueue.length > 0 && s.sendWindow > 0) {\n const head = s.sendQueue[0]!;\n const n = Math.min(head.byteLength, s.sendWindow, maxPayload);\n const chunk = head.subarray(0, n);\n if (n === head.byteLength) s.sendQueue.shift();\n else s.sendQueue[0] = head.subarray(n);\n s.sendWindow -= n;\n s.sendSeq += 1;\n socket.send(encodeFrame({ version: FRAME_VERSION, flags: 0, channel: FrameChannel.STDIN, cid: 0, sid: s.sid, seq: s.sendSeq }, chunk));\n }\n }\n\n function endStream(s: StreamState, reason: EndReason | null, error: DesktopProtocolError | null): void {\n if (s.ended) return;\n s.ended = true;\n s.sendQueue = [];\n if (!s.resultSettled) {\n s.resultSettled = true;\n s.rejectResult(error ?? new DesktopProtocolError(\"INTERNAL\", \"Stream ended before its result\"));\n }\n if (error) s.rejectDone(error);\n else s.resolveDone(reason ?? \"completed\");\n }\n\n function reattach(s: StreamState, welcome: Welcome): void {\n const id = newId(\"a\");\n streams.delete(s.id);\n s.id = id;\n s.reattaching = true;\n s.expectSeq = s.lastSeq > 0 ? s.lastSeq + 1 : null;\n s.consumedUncredited = 0;\n s.sendWindow = welcome.limits.default_window_bytes;\n s.sendSeq = 0;\n streams.set(id, s);\n const params: Record<string, unknown> = { resource_id: s.resourceId, mode: s.options.mode ?? \"control\" };\n if (s.lastSeq > 0) params.since_seq = s.lastSeq;\n if (s.options.windowBytes !== undefined) params.window_bytes = s.options.windowBytes;\n sendJson({ id, type: \"request\", cap: \"session\", op: \"attach\", params });\n }\n\n function safeCall(where: string, fn: () => void): void {\n try {\n fn();\n } catch (error) {\n diagnose({ kind: \"handler_threw\", where, error });\n }\n }\n\n // ── public API ─────────────────────────────────────────────────────────────\n\n function ready(opts: RequestOptions = {}): Promise<Welcome> {\n if (state.status === \"open\" && state.welcome) return Promise.resolve(state.welcome);\n if (state.status === \"closed\") {\n return Promise.reject(state.lastError ?? new DesktopProtocolError(\"CANCELLED\", \"Client is closed\"));\n }\n if (state.status === \"idle\") connect();\n return new Promise((resolve, reject) => {\n const waiter = {\n resolve: (w: Welcome) => {\n done();\n resolve(w);\n },\n reject: (e: DesktopProtocolError) => {\n done();\n reject(e);\n },\n };\n const timeoutMs = opts.timeoutMs ?? requestTimeoutMs;\n const timer = timers.setTimeout(() => waiter.reject(new DesktopProtocolError(\"DEVICE_OFFLINE\", \"Device not reachable\", { retryable: true })), timeoutMs);\n const onAbort = () => waiter.reject(new DesktopProtocolError(\"CANCELLED\", \"Aborted\"));\n opts.signal?.addEventListener(\"abort\", onAbort, { once: true });\n function done() {\n readyWaiters.delete(waiter);\n timers.clearTimeout(timer);\n opts.signal?.removeEventListener(\"abort\", onAbort);\n }\n readyWaiters.add(waiter);\n });\n }\n\n async function request<N extends OpName>(op: N, params: OpParams<N>, opts: RequestOptions = {}): Promise<OpResult<N>> {\n if (OPS[op].kind !== \"unary\") {\n throw new DesktopProtocolError(\"INVALID_PARAMS\", `${op} is a ${OPS[op].kind} op — use stream()`);\n }\n await ready(opts);\n const id = newId(\"r\");\n if (opts.onRequestId) safeCall(\"onRequestId\", () => opts.onRequestId?.(id));\n return new Promise<OpResult<N>>((resolve, reject) => {\n const timeoutMs = opts.timeoutMs ?? requestTimeoutMs;\n const timer = timers.setTimeout(() => {\n pending.delete(id);\n cleanup();\n abandon(id);\n reject(new DesktopProtocolError(\"TIMEOUT\", `${op} timed out`, { retryable: true }));\n }, timeoutMs);\n const onAbort = () => {\n pending.delete(id);\n cleanup();\n abandon(id);\n reject(new DesktopProtocolError(\"CANCELLED\", \"Aborted\"));\n };\n function cleanup() {\n timers.clearTimeout(timer);\n opts.signal?.removeEventListener(\"abort\", onAbort);\n }\n opts.signal?.addEventListener(\"abort\", onAbort, { once: true });\n pending.set(id, { kind: \"unary\", op, resolve: resolve as (v: unknown) => void, reject, cleanup });\n if (!sendJson({ id, type: \"request\", ...capOf(op), params })) {\n pending.delete(id);\n cleanup();\n reject(new DesktopProtocolError(\"DEVICE_OFFLINE\", \"Connection lost\", { retryable: true }));\n }\n });\n }\n\n function stream<N extends StreamOpName>(\n op: N,\n params: OpParams<N>,\n handlers: StreamHandlers = {},\n opts: StreamOptions = {},\n ): DesktopStream<N> {\n let resolveResult!: (v: unknown) => void;\n let rejectResult!: (e: DesktopProtocolError) => void;\n let resolveDone!: (r: EndReason) => void;\n let rejectDone!: (e: DesktopProtocolError) => void;\n const result = new Promise<OpResult<N>>((res, rej) => {\n resolveResult = res as (v: unknown) => void;\n rejectResult = rej;\n });\n const done = new Promise<EndReason>((res, rej) => {\n resolveDone = res;\n rejectDone = rej;\n });\n // Consumers often await only one of the two; never leave the other as an unhandled rejection.\n result.catch(() => undefined);\n done.catch(() => undefined);\n\n // A caller-started session.attach (a page reload reattaching by the resource id it kept in its\n // URL) is a resource stream from its first byte: it survives drops like the stream that created\n // the resource, and its sequence continues from since_seq rather than from 1.\n const attach = op === \"session.attach\" ? (params as { resource_id: string; since_seq?: number }) : null;\n const s: StreamState = {\n op,\n handlers,\n options: opts,\n id: newId(\"s\"),\n sid: null,\n resourceId: attach ? attach.resource_id : null,\n lastSeq: attach?.since_seq ?? 0,\n expectSeq: attach ? (attach.since_seq === undefined ? null : attach.since_seq + 1) : 1,\n windowBytes: opts.windowBytes ?? DEFAULT_WINDOW_BYTES,\n consumedUncredited: 0,\n sendWindow: DEFAULT_WINDOW_BYTES,\n sendSeq: 0,\n sendQueue: [],\n chain: Promise.resolve(),\n resultSettled: false,\n resolveResult,\n rejectResult,\n resolveDone,\n rejectDone,\n ended: false,\n reattaching: false,\n };\n\n const start = async () => {\n let welcome: Welcome;\n try {\n welcome = await ready(opts);\n } catch (error) {\n endStream(s, null, error as DesktopProtocolError);\n return;\n }\n if (s.ended) return;\n s.sendWindow = welcome.limits.default_window_bytes;\n if (opts.windowBytes === undefined) s.windowBytes = welcome.limits.default_window_bytes;\n streams.set(s.id, s);\n const wire: Record<string, unknown> = { ...(params as Record<string, unknown>) };\n if (opts.windowBytes !== undefined && \"window_bytes\" in OPS[op].params.shape) wire.window_bytes = opts.windowBytes;\n if (!sendJson({ id: s.id, type: \"request\", ...capOf(op), params: wire })) {\n streams.delete(s.id);\n endStream(s, null, new DesktopProtocolError(\"DEVICE_OFFLINE\", \"Connection lost\", { retryable: true }));\n }\n };\n void start();\n opts.signal?.addEventListener(\"abort\", () => handle.cancel(), { once: true });\n\n const encoder = new TextEncoder();\n const handle: DesktopStream<N> = {\n get id() {\n return s.id;\n },\n result,\n done,\n get resourceId() {\n return s.resourceId;\n },\n get lastSeq() {\n return s.lastSeq;\n },\n write(data) {\n if (s.ended) throw new DesktopProtocolError(\"RESOURCE_GONE\", \"Stream has ended\");\n const bytes = typeof data === \"string\" ? encoder.encode(data) : data;\n if (bytes.byteLength === 0) return;\n s.sendQueue.push(bytes);\n flushSend(s);\n },\n cancel() {\n if (s.ended) return;\n if (!sendJson({ id: s.id, type: \"cancel\" })) {\n streams.delete(s.id);\n endStream(s, \"cancelled\", null);\n }\n },\n async detach() {\n if (s.ended) return;\n if (s.resourceId === null) throw new DesktopProtocolError(\"INVALID_PARAMS\", \"Only resource streams can be detached\");\n const resourceId = s.resourceId;\n streams.delete(s.id);\n if (s.sid !== null) bySid.delete(s.sid);\n endStream(s, \"detached\", null);\n await request(\"session.detach\", { resource_id: resourceId });\n },\n };\n return handle;\n }\n\n function on<E extends EventName>(name: E, handler: EventHandler<E>): () => void {\n let set = eventHandlers.get(name);\n if (!set) {\n set = new Set();\n eventHandlers.set(name, set);\n }\n set.add(handler as EventHandler<EventName>);\n return () => {\n set.delete(handler as EventHandler<EventName>);\n };\n }\n\n function reauth(token: string): void {\n sendJson({ type: \"relay\", op: \"reauth\", token });\n }\n\n function wake(opts: WakeOptions = {}): void {\n if (closedByUser || state.status === \"closed\") return;\n if (state.status === \"idle\" || state.status === \"reconnecting\") {\n connect(); // dial now; connect() cancels the scheduled backoff timer\n return;\n }\n if (state.status === \"connecting\" || !socket || probeTimer !== null) return;\n const generation = socketGeneration;\n const heardBefore = heardCount;\n try {\n socket.send(PING_TEXT);\n } catch {\n // A socket that cannot even send is dead: fall through to the probe verdict.\n }\n probeTimer = timers.setTimeout(() => {\n probeTimer = null;\n if (generation !== socketGeneration || !socket) return;\n if (heardCount > heardBefore) return; // answered: the socket is alive\n const silentMs = timers.now() - lastHeardAt;\n diagnose({ kind: \"heartbeat_timeout\", silentMs });\n const dead = socket;\n onSocketGone(generation, null, new DesktopProtocolError(\"TIMEOUT\", \"Connection went silent\", { retryable: true }));\n try {\n dead.close(CloseCode.NORMAL, \"wake probe timeout\");\n } catch {\n // already closing\n }\n if (state.status === \"reconnecting\") connect(); // the person is looking: no backoff wait\n }, opts.probeMs ?? 4000);\n }\n\n return {\n connect,\n close,\n getState: () => state,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n ready,\n request,\n stream,\n on,\n reauth,\n wake,\n };\n}\n\nexport { RECONNECT_ALARM_ATTEMPTS };\n","/**\n * Wire a client's wake() to the browser events that mean \"the person is back\": the page becomes\n * visible again (iOS Safari suspends a background tab's sockets), a back/forward-cache restore\n * (`pageshow` with persisted), and the network returning (`online`). Framework-free; the React\n * binding is `useDesktopWake` in `./react`.\n */\nimport type { DesktopClient, WakeOptions } from \"./types\";\n\n/** The subset of window/document the binding listens on — injectable for tests and non-DOM hosts. */\nexport interface WakeTargets {\n window: Pick<Window, \"addEventListener\" | \"removeEventListener\">;\n document: Pick<Document, \"addEventListener\" | \"removeEventListener\" | \"visibilityState\">;\n}\n\nexport function bindDesktopWake(client: Pick<DesktopClient, \"wake\">, options: WakeOptions & { targets?: WakeTargets } = {}): () => void {\n const targets: WakeTargets | null =\n options.targets ?? (typeof window !== \"undefined\" && typeof document !== \"undefined\" ? { window, document } : null);\n if (!targets) return () => undefined;\n const wakeOptions: WakeOptions = options.probeMs === undefined ? {} : { probeMs: options.probeMs };\n const onVisibility = () => {\n if (targets.document.visibilityState === \"visible\") client.wake(wakeOptions);\n };\n const onWake = () => client.wake(wakeOptions);\n targets.document.addEventListener(\"visibilitychange\", onVisibility);\n targets.window.addEventListener(\"pageshow\", onWake);\n targets.window.addEventListener(\"online\", onWake);\n targets.window.addEventListener(\"focus\", onWake);\n return () => {\n targets.document.removeEventListener(\"visibilitychange\", onVisibility);\n targets.window.removeEventListener(\"pageshow\", onWake);\n targets.window.removeEventListener(\"online\", onWake);\n targets.window.removeEventListener(\"focus\", onWake);\n };\n}\n","import { DesktopProtocolError } from \"../error\";\nimport type { MlProgress, ModelsTranscribeResult, TranscriptionModelId } from \"../schema/models\";\nimport type { DesktopClient } from \"./types\";\n\n/** fs.write carries at most 4 MiB of bytes (base64 in one message). */\nexport const DESKTOP_TRANSCRIBE_MAX_BYTES = 4 * 1024 * 1024;\n\nexport interface DesktopTranscriberOptions {\n /** Whisper size; omitted = the device's default. */\n model?: TranscriptionModelId;\n /** ISO 639-1; omitted = detect. */\n language?: string;\n /** Per call (first use installs the runtime and a model): default 15 minutes. */\n timeoutMs?: number;\n /** Progress for each call (install steps, then each segment as it is recognized). */\n onProgress?: (progress: MlProgress) => void;\n}\n\n/** What a transcription returns: the shape `@ai-matrx/browser-audio`'s TranscriptionTransport expects. */\nexport interface DesktopTranscript {\n text: string;\n language: string;\n duration: number;\n segments: Array<{ start: number; end: number; text: string }>;\n result: ModelsTranscribeResult;\n}\n\nexport interface DesktopTranscriber {\n /** Transcribe recorded audio on the device: written to its temp folder, transcribed, removed. */\n transcribe(file: Blob, signal?: AbortSignal): Promise<DesktopTranscript>;\n}\n\nconst EXT: Record<string, string> = {\n \"audio/webm\": \"webm\",\n \"audio/ogg\": \"ogg\",\n \"audio/mp4\": \"m4a\",\n \"audio/mpeg\": \"mp3\",\n \"audio/wav\": \"wav\",\n \"audio/x-wav\": \"wav\",\n \"video/webm\": \"webm\",\n \"video/mp4\": \"mp4\",\n};\n\nfunction base64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 0x8000) binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));\n return btoa(binary);\n}\n\n/**\n * Speech to text on the person's own computer, from any surface connected to it (the app's\n * screen, the web app or the phone through the relay). Structurally a\n * `@ai-matrx/browser-audio` TranscriptionTransport, so every voice input on the platform can\n * transcribe locally: `new BrowserAudioKernel({ transport: createDesktopTranscriber(client) })`.\n *\n * Audio travels as one `fs.write` into the device's temp folder (at most 4 MiB; longer\n * recordings are chunked by the kernel), then `models.transcribe`, then `fs.delete` — every step\n * an ordinary op, so this works through every transport with no special path.\n */\nexport function createDesktopTranscriber(client: DesktopClient, options: DesktopTranscriberOptions = {}): DesktopTranscriber {\n let temp: Promise<string> | null = null;\n const tempDir = () => (temp ??= client.request(\"sysinfo.get\", {}).then((s) => s.paths.temp.replace(/\\/$/, \"\")));\n\n return {\n async transcribe(file, signal) {\n if (file.size > DESKTOP_TRANSCRIBE_MAX_BYTES) {\n throw new DesktopProtocolError(\"PAYLOAD_TOO_LARGE\", \"Recording is larger than 4 MB\", { retryable: false, data: { limit_bytes: DESKTOP_TRANSCRIBE_MAX_BYTES } });\n }\n const type = file.type.split(\";\")[0]?.trim() ?? \"\";\n const name = `matrx-transcribe-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}.${EXT[type] ?? \"webm\"}`;\n const path = `${await tempDir()}/${name}`;\n const bytes = new Uint8Array(await file.arrayBuffer());\n await client.request(\"fs.write\", { path, content: base64(bytes), encoding: \"base64\", mode: 0o600 }, signal ? { signal } : {});\n let requestId = \"\";\n const off = options.onProgress\n ? client.on(\"models.progress\", (payload) => {\n if (payload.request_id === requestId) options.onProgress?.(payload.progress);\n })\n : () => undefined;\n try {\n const result = await client.request(\n \"models.transcribe\",\n { path, ...(options.model ? { model: options.model } : {}), ...(options.language ? { language: options.language } : {}) },\n { timeoutMs: options.timeoutMs ?? 15 * 60_000, onRequestId: (id) => (requestId = id), ...(signal ? { signal } : {}) },\n );\n return {\n text: result.text,\n language: result.language,\n duration: result.duration_s,\n segments: result.segments.map((s) => ({ start: s.start_s, end: s.end_s, text: s.text })),\n result,\n };\n } finally {\n off();\n void client.request(\"fs.delete\", { path, to_trash: false }).catch(() => undefined);\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/client/client.ts","../src/client/wake.ts","../src/client/transcribe.ts"],"sourcesContent":["/**\n * The reconnecting desktop-protocol client: hello → requests, streams with credit-based\n * backpressure, events, transparent reattach of resource streams (terminals, watches) after a\n * drop, heartbeat, and relay reauth. One instance per device connection. All state lives in the\n * closure — no module-level state (dual ESM/CJS graphs would split it).\n */\nimport { RECONNECT_ALARM_ATTEMPTS, createBackoff } from \"@ai-matrx/data/realtime\";\nimport { DesktopProtocolError } from \"../error\";\nimport { FRAME_VERSION, FrameChannel, decodeFrame, encodeFrame } from \"../frame\";\nimport type { FrameHeader } from \"../frame\";\nimport { closeRule } from \"../close-policy\";\nimport { CloseCode, CoreToClientMsg, PING_TEXT, PONG_TEXT, Welcome } from \"../schema/envelope\";\nimport type { EndReason, StreamMeta } from \"../schema/envelope\";\nimport type { ProtocolErrorBody } from \"../schema/errors\";\nimport { DEFAULT_MAX_FRAME_PAYLOAD_BYTES, DEFAULT_WINDOW_BYTES } from \"../schema/frame\";\nimport { PROTOCOL_MAJOR, PROTOCOL_MINOR } from \"../schema/primitives\";\nimport { EVENTS, OPS } from \"../schema/registry\";\nimport { knows } from \"../versioning\";\nimport type { OpName, OpParams, OpResult } from \"../schema/registry\";\nimport type {\n ClientTimers,\n DesktopClient,\n DesktopClientDiagnostic,\n DesktopClientOptions,\n DesktopClientState,\n DesktopStream,\n EventHandler,\n EventName,\n RequestOptions,\n StreamHandlers,\n StreamOpName,\n StreamOptions,\n WakeOptions,\n WebSocketFactory,\n WebSocketLike,\n} from \"./types\";\n\nconst WS_OPEN = 1;\ntype Pending = {\n kind: \"unary\";\n op: string;\n resolve: (value: unknown) => void;\n reject: (error: DesktopProtocolError) => void;\n cleanup: () => void;\n};\n\ninterface StreamState {\n op: string;\n handlers: StreamHandlers;\n options: StreamOptions;\n id: string;\n sid: number | null;\n resourceId: string | null;\n /** Last inbound DATA seq delivered to the consumer. */\n lastSeq: number;\n /** Expected next inbound seq, or null right after a gap/snapshot (resync on next frame). */\n expectSeq: number | null;\n windowBytes: number;\n /** Consumed bytes not yet credited back. */\n consumedUncredited: number;\n /** Outbound (STDIN) credit granted by the core. */\n sendWindow: number;\n sendSeq: number;\n sendQueue: Uint8Array[];\n /** Serializes consumer callbacks so credits follow consumption order. */\n chain: Promise<void>;\n resultSettled: boolean;\n resolveResult: (value: unknown) => void;\n rejectResult: (error: DesktopProtocolError) => void;\n resolveDone: (reason: EndReason) => void;\n rejectDone: (error: DesktopProtocolError) => void;\n ended: boolean;\n /** True while a reattach request is in flight for it. */\n reattaching: boolean;\n /** The first-frame deadline, until the stream hears anything back. */\n firstFrameTimer: unknown;\n}\n\nconst defaultTimers: ClientTimers = {\n setTimeout: (fn, ms) => globalThis.setTimeout(fn, ms),\n clearTimeout: (handle) => globalThis.clearTimeout(handle as ReturnType<typeof globalThis.setTimeout>),\n now: () => Date.now(),\n};\n\nfunction defaultWebSocket(): WebSocketFactory {\n return (url, protocols) => {\n const Ctor = (globalThis as { WebSocket?: new (url: string, protocols?: string[]) => WebSocketLike }).WebSocket;\n if (!Ctor) {\n throw new DesktopProtocolError(\"PLATFORM_UNSUPPORTED\", \"No global WebSocket — pass options.webSocket\");\n }\n return new Ctor(url, protocols);\n };\n}\n\nfunction capOf(op: string): { cap: string; op: string } {\n const dot = op.indexOf(\".\");\n return { cap: op.slice(0, dot), op: op.slice(dot + 1) };\n}\n\nfunction fromBody(body: ProtocolErrorBody): DesktopProtocolError {\n return body.data === undefined\n ? new DesktopProtocolError(body.code, body.message, { retryable: body.retryable })\n : new DesktopProtocolError(body.code, body.message, { retryable: body.retryable, data: body.data });\n}\n\nfunction toBytes(data: unknown): Uint8Array | null {\n if (data instanceof ArrayBuffer) return new Uint8Array(data);\n if (ArrayBuffer.isView(data)) return new Uint8Array(data.buffer, data.byteOffset, data.byteLength);\n return null;\n}\n\nexport function createDesktopClient(options: DesktopClientOptions): DesktopClient {\n const timers = options.timers ?? defaultTimers;\n const makeSocket = options.webSocket ?? defaultWebSocket();\n const heartbeatMs = options.heartbeatMs ?? 25_000;\n const requestTimeoutMs = options.requestTimeoutMs ?? 70_000;\n const firstFrameMs = options.firstFrameMs ?? requestTimeoutMs;\n const protocolVersion = options.protocolVersion ?? `${PROTOCOL_MAJOR}.${PROTOCOL_MINOR}`;\n const backoff = createBackoff({ ...options.backoff, now: timers.now });\n const diagnose =\n options.onDiagnostic ??\n ((d: DesktopClientDiagnostic) => {\n console.warn(\"[desktop-protocol]\", d.kind, d);\n });\n\n let state: DesktopClientState = {\n status: \"idle\",\n welcome: null,\n attempts: 0,\n retryInMs: null,\n lastError: null,\n lastCloseCode: null,\n outcome: null,\n };\n /** Token refusals (4001/4008) since the last welcome; the second in a row is terminal. */\n let authRefusals = 0;\n const listeners = new Set<() => void>();\n const readyWaiters = new Set<{ resolve: (w: Welcome) => void; reject: (e: DesktopProtocolError) => void }>();\n const pending = new Map<string, Pending>();\n // Requests this client gave up on (aborted or timed out) after telling the core \"cancel\". The\n // core still answers each one exactly once — CANCELLED, or the result if it finished first — so\n // that one answer is expected and consumed here, not reported as unknown_request. Bounded: an\n // answer that never comes cannot grow it past ABANDONED_MAX; a dropped socket clears it.\n const abandoned = new Set<string>();\n const ABANDONED_MAX = 1024;\n function abandon(id: string): void {\n if (!sendJson({ id, type: \"cancel\" })) return;\n abandoned.add(id);\n if (abandoned.size > ABANDONED_MAX) abandoned.delete(abandoned.values().next().value as string);\n }\n const streams = new Map<string, StreamState>(); // by current request id\n const bySid = new Map<number, StreamState>();\n const eventHandlers = new Map<string, Set<EventHandler<EventName>>>();\n let socket: WebSocketLike | null = null;\n let socketGeneration = 0;\n let nextId = 0;\n let helloId: string | null = null;\n let reconnectTimer: unknown = null;\n let heartbeatTimer: unknown = null;\n let probeTimer: unknown = null;\n let lastHeardAt = 0;\n /** Inbound messages on the current socket — the wake probe's \"was anything heard since?\" */\n let heardCount = 0;\n /** Heartbeat answers on the current socket (reported when it closes). */\n let pongs = 0;\n let closedByUser = false;\n\n const newId = (prefix: string) => `${prefix}${(++nextId).toString(36)}`;\n\n function setState(patch: Partial<DesktopClientState>): void {\n state = { ...state, ...patch };\n for (const listener of [...listeners]) {\n try {\n listener();\n } catch (error) {\n diagnose({ kind: \"handler_threw\", where: \"subscribe listener\", error });\n }\n }\n }\n\n function sendJson(message: unknown): boolean {\n if (!socket || socket.readyState !== WS_OPEN) return false;\n socket.send(JSON.stringify(message));\n return true;\n }\n\n // ── connection lifecycle ────────────────────────────────────────────────────\n\n function connect(): void {\n if (state.status === \"connecting\" || state.status === \"handshaking\" || state.status === \"open\") return;\n if (state.status === \"closed\" || state.status === \"idle\") authRefusals = 0; // a deliberate (re)start\n closedByUser = false;\n if (reconnectTimer !== null) {\n timers.clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n void openSocket();\n }\n\n async function openSocket(): Promise<void> {\n const generation = ++socketGeneration;\n setState({ status: \"connecting\", retryInMs: null });\n let ws: WebSocketLike;\n try {\n const url = typeof options.url === \"function\" ? await options.url() : options.url;\n const protocols = options.protocols ? await options.protocols() : [];\n if (generation !== socketGeneration || closedByUser) return;\n ws = makeSocket(url, protocols);\n } catch (error) {\n if (generation !== socketGeneration) return;\n const err =\n error instanceof DesktopProtocolError\n ? error\n : new DesktopProtocolError(\"INTERNAL\", \"Could not open the connection\", { retryable: true, cause: error });\n onSocketGone(generation, null, err);\n return;\n }\n socket = ws;\n ws.binaryType = \"arraybuffer\";\n ws.onopen = () => {\n if (generation !== socketGeneration) return;\n lastHeardAt = timers.now();\n pongs = 0;\n helloId = newId(\"h\");\n setState({ status: \"handshaking\" });\n sendJson({ type: \"hello\", id: helloId, protocolVersion, clientType: options.clientType, clientVersion: options.clientVersion });\n scheduleHeartbeat(generation);\n };\n ws.onmessage = (event) => {\n if (generation !== socketGeneration) return;\n lastHeardAt = timers.now();\n heardCount++;\n onMessage(event.data);\n };\n ws.onerror = () => {\n // The close event that always follows carries the code; nothing to do here.\n };\n ws.onclose = (event) => {\n if (generation !== socketGeneration) return;\n const ev = event as { code: number; reason?: string; wasClean?: boolean };\n reportClose(ev.code, ev.reason ?? \"\", ev.wasClean ?? false);\n onSocketGone(generation, event.code, null);\n };\n }\n\n function scheduleHeartbeat(generation: number): void {\n if (heartbeatTimer !== null) timers.clearTimeout(heartbeatTimer);\n heartbeatTimer = timers.setTimeout(() => {\n heartbeatTimer = null;\n if (generation !== socketGeneration || !socket) return;\n const silentMs = timers.now() - lastHeardAt;\n if (silentMs >= heartbeatMs * 2) {\n diagnose({ kind: \"heartbeat_timeout\", silentMs });\n reportClose(null, \"heartbeat timeout\", false);\n const dead = socket;\n onSocketGone(generation, null, new DesktopProtocolError(\"TIMEOUT\", \"Connection went silent\", { retryable: true }));\n try {\n dead.close(CloseCode.NORMAL, \"heartbeat timeout\");\n } catch {\n // already closing\n }\n return;\n }\n if (socket.readyState === WS_OPEN) socket.send(PING_TEXT);\n scheduleHeartbeat(generation);\n }, heartbeatMs);\n }\n\n function reportClose(code: number | null, reason: string, wasClean: boolean): void {\n diagnose({ kind: \"socket_closed\", code, reason: reason.slice(0, 120), wasClean, idleSinceLastRxMs: Math.max(0, timers.now() - lastHeardAt), pongs });\n }\n\n /** The socket is gone (close event, open failure or heartbeat death). */\n function onSocketGone(generation: number, code: number | null, error: DesktopProtocolError | null): void {\n if (generation !== socketGeneration) return;\n socketGeneration++; // ignore anything the dead socket still emits\n if (socket) {\n socket.onopen = socket.onmessage = socket.onclose = socket.onerror = null;\n }\n socket = null;\n helloId = null;\n if (heartbeatTimer !== null) {\n timers.clearTimeout(heartbeatTimer);\n heartbeatTimer = null;\n }\n if (probeTimer !== null) {\n timers.clearTimeout(probeTimer);\n probeTimer = null;\n }\n // The one close table (close-policy.ts) decides: retry, retry with a fresh token, or stop.\n const rule = code === null ? null : closeRule(code);\n if (rule?.action === \"reauth\") authRefusals++;\n const stopped = rule !== null && (rule.action === \"stop\" || (rule.action === \"reauth\" && authRefusals >= 2));\n const terminal = stopped && rule ? rule : undefined;\n const lost =\n error ??\n (terminal\n ? new DesktopProtocolError(terminal.error[0], terminal.error[1])\n : rule && rule.action === \"reauth\"\n ? new DesktopProtocolError(rule.error[0], rule.error[1], { retryable: true })\n : new DesktopProtocolError(\"DEVICE_OFFLINE\", \"Connection lost\", { retryable: true }));\n\n // Unary requests cannot survive a drop: the caller decides whether to retry.\n abandoned.clear();\n for (const [id, p] of pending) {\n pending.delete(id);\n p.cleanup();\n p.reject(lost);\n }\n // Resource streams survive (reattach on reconnect); everything else ends now.\n bySid.clear();\n for (const [id, s] of streams) {\n if (s.resourceId !== null && terminal === undefined && !closedByUser) {\n s.sid = null;\n s.reattaching = false;\n continue;\n }\n streams.delete(id);\n endStream(s, null, lost);\n }\n\n if (closedByUser || terminal) {\n setState({\n status: \"closed\",\n welcome: null,\n lastError: closedByUser ? state.lastError : lost,\n lastCloseCode: code,\n retryInMs: null,\n outcome: closedByUser ? null : (terminal?.outcome ?? null),\n });\n rejectReadyWaiters(lost);\n return;\n }\n const delay = backoff.nextDelayMs();\n if (backoff.isAlarming()) diagnose({ kind: \"reconnect_alarm\", attempts: backoff.attempts() });\n setState({ status: \"reconnecting\", welcome: null, attempts: backoff.attempts(), retryInMs: delay, lastError: lost, lastCloseCode: code });\n reconnectTimer = timers.setTimeout(() => {\n reconnectTimer = null;\n if (!closedByUser) void openSocket();\n }, delay);\n }\n\n function rejectReadyWaiters(error: DesktopProtocolError): void {\n for (const w of [...readyWaiters]) {\n readyWaiters.delete(w);\n w.reject(error);\n }\n }\n\n function close(): void {\n closedByUser = true;\n if (reconnectTimer !== null) {\n timers.clearTimeout(reconnectTimer);\n reconnectTimer = null;\n }\n const cancelled = new DesktopProtocolError(\"CANCELLED\", \"Client closed\");\n const ws = socket;\n if (ws) {\n onSocketGone(socketGeneration, CloseCode.NORMAL, cancelled);\n try {\n ws.close(CloseCode.NORMAL, \"client closed\");\n } catch {\n // already closed\n }\n } else {\n for (const [id, s] of streams) {\n streams.delete(id);\n endStream(s, null, cancelled);\n }\n setState({ status: \"closed\", retryInMs: null });\n rejectReadyWaiters(cancelled);\n }\n }\n\n // ── inbound ────────────────────────────────────────────────────────────────\n\n function onMessage(data: unknown): void {\n if (typeof data === \"string\") {\n if (data === PONG_TEXT) {\n pongs++;\n return;\n }\n let json: unknown;\n try {\n json = JSON.parse(data);\n } catch {\n diagnose({ kind: \"malformed_message\", detail: \"not JSON\" });\n return;\n }\n const parsed = CoreToClientMsg.safeParse(json);\n if (!parsed.success) {\n diagnose({ kind: \"malformed_message\", detail: parsed.error.issues.map((i) => `${i.path.join(\".\")}: ${i.message}`).join(\"; \") });\n return;\n }\n onEnvelope(parsed.data);\n return;\n }\n const bytes = toBytes(data);\n if (bytes === null) {\n diagnose({ kind: \"malformed_message\", detail: \"binary message is not an ArrayBuffer/view (set binaryType)\" });\n return;\n }\n let frame: ReturnType<typeof decodeFrame>;\n try {\n frame = decodeFrame(bytes);\n } catch (error) {\n diagnose({ kind: \"malformed_message\", detail: error instanceof Error ? error.message : String(error) });\n return;\n }\n onFrame(frame.header, frame.payload);\n }\n\n function onEnvelope(msg: CoreToClientMsg): void {\n if (msg.type !== \"event\") {\n const heard = streams.get(msg.id);\n if (heard) clearFirstFrame(heard);\n }\n switch (msg.type) {\n case \"response\": {\n if (msg.id === helloId) return onWelcome(msg.result);\n const s = streams.get(msg.id);\n if (s) return onStreamResult(s, msg.result);\n const p = pending.get(msg.id);\n if (!p) {\n if (abandoned.delete(msg.id)) return; // the one answer to a request we cancelled\n return diagnose({ kind: \"unknown_request\", id: msg.id, type: msg.type });\n }\n pending.delete(msg.id);\n p.cleanup();\n p.resolve(msg.result);\n return;\n }\n case \"error\": {\n const error = fromBody(msg.error);\n if (msg.id === helloId) return onHelloRefused(error);\n const s = streams.get(msg.id);\n if (s) {\n if (s.reattaching && s.resourceId !== null) diagnose({ kind: \"reattach_failed\", resourceId: s.resourceId, error });\n streams.delete(msg.id);\n if (s.sid !== null) bySid.delete(s.sid);\n return endStream(s, null, error);\n }\n const p = pending.get(msg.id);\n if (!p) {\n if (abandoned.delete(msg.id)) return; // the one answer to a request we cancelled\n return diagnose({ kind: \"unknown_request\", id: msg.id, type: msg.type });\n }\n pending.delete(msg.id);\n p.cleanup();\n p.reject(error);\n return;\n }\n case \"stream\": {\n const s = streams.get(msg.id);\n if (!s) return diagnose({ kind: \"unknown_request\", id: msg.id, type: msg.type });\n onStreamMeta(s, msg.meta);\n return;\n }\n case \"end\": {\n const s = streams.get(msg.id);\n if (!s) return diagnose({ kind: \"unknown_request\", id: msg.id, type: msg.type });\n // Deliver everything already queued before announcing the end.\n void s.chain.then(() => {\n streams.delete(s.id);\n if (s.sid !== null) bySid.delete(s.sid);\n endStream(s, msg.reason ?? \"completed\", null);\n });\n return;\n }\n case \"credit\": {\n const s = streams.get(msg.id);\n if (!s) return diagnose({ kind: \"unknown_request\", id: msg.id, type: msg.type });\n s.sendWindow += msg.n;\n flushSend(s);\n return;\n }\n case \"event\": {\n const key = `${msg.cap}.${msg.name}`;\n const schema = (EVENTS as Record<string, (typeof EVENTS)[EventName]>)[key];\n if (!schema) return diagnose({ kind: \"malformed_message\", detail: `unknown event ${key}` });\n const payload = schema.safeParse(msg.payload);\n if (!payload.success) return diagnose({ kind: \"malformed_message\", detail: `event ${key}: invalid payload` });\n if (key === \"relay.auth_expiring\" && options.getToken) {\n options.getToken().then(reauth, (error: unknown) => diagnose({ kind: \"reauth_failed\", error }));\n }\n for (const handler of [...(eventHandlers.get(key) ?? [])]) {\n try {\n handler(payload.data as never, msg.resourceId);\n } catch (error) {\n diagnose({ kind: \"handler_threw\", where: `event ${key}`, error });\n }\n }\n return;\n }\n }\n }\n\n function onWelcome(result: unknown): void {\n const welcome = Welcome.safeParse(result);\n if (!welcome.success) {\n onHelloRefused(new DesktopProtocolError(\"PROTOCOL_ERROR\", \"Malformed welcome\"));\n return;\n }\n helloId = null;\n backoff.markConnected();\n authRefusals = 0;\n setState({ status: \"open\", welcome: welcome.data, attempts: 0, retryInMs: null, lastError: null, outcome: null });\n // 1.38: say what this client is (\"iPhone\"), first on the wire, so \"Started from iPhone\" is the\n // core's own stamp. Never to an older core (a hello field would have made it refuse the hello).\n if (options.clientLabel && knows(welcome.data.protocol_version, \"1.38\")) {\n void request(\"session.identify\", { label: options.clientLabel.slice(0, 60) }).catch((error: unknown) =>\n diagnose({ kind: \"handler_threw\", where: \"session.identify\", error }),\n );\n }\n for (const w of [...readyWaiters]) {\n readyWaiters.delete(w);\n w.resolve(welcome.data);\n }\n // Transparent reattach: every surviving resource stream continues where its consumer stopped.\n for (const s of [...streams.values()]) {\n if (s.sid === null && s.resourceId !== null && !s.ended) reattach(s, welcome.data);\n }\n }\n\n function onHelloRefused(error: DesktopProtocolError): void {\n // An unsupported version will not fix itself on retry: UPGRADE_REQUIRED is a terminal close.\n const ws = socket;\n onSocketGone(socketGeneration, error.code === \"PROTOCOL_VERSION_UNSUPPORTED\" ? CloseCode.UPGRADE_REQUIRED : null, error);\n try {\n ws?.close(CloseCode.NORMAL, \"hello refused\");\n } catch {\n // already closed\n }\n }\n\n // ── streams ────────────────────────────────────────────────────────────────\n\n function onStreamResult(s: StreamState, result: unknown): void {\n if (s.reattaching) {\n // session.attach result = ResourceInfo; the stream continues on the new id.\n s.reattaching = false;\n safeCall(\"onReattached\", () => s.handlers.onReattached?.());\n return;\n }\n const rid = (result as { resource_id?: unknown } | null)?.resource_id;\n if (typeof rid === \"string\") s.resourceId = rid;\n if (!s.resultSettled) {\n s.resultSettled = true;\n s.resolveResult(result);\n }\n }\n\n function onStreamMeta(s: StreamState, meta: StreamMeta): void {\n if (meta.kind === \"open\") {\n if (s.sid !== null) bySid.delete(s.sid);\n s.sid = meta.sid;\n s.windowBytes = meta.window_bytes;\n if (meta.resource_id !== undefined) s.resourceId = meta.resource_id;\n bySid.set(meta.sid, s);\n flushSend(s);\n } else {\n // gap or snapshot: the next DATA frame re-establishes the sequence.\n s.expectSeq = null;\n }\n safeCall(\"onMeta\", () => s.handlers.onMeta?.(meta));\n }\n\n function onFrame(header: FrameHeader, payload: Uint8Array): void {\n const s = bySid.get(header.sid);\n if (!s) {\n diagnose({ kind: \"unknown_stream\", sid: header.sid });\n return;\n }\n clearFirstFrame(s);\n const isData = header.channel === FrameChannel.DATA || header.channel === FrameChannel.STDERR;\n const isSnapshot = header.channel === FrameChannel.SNAPSHOT;\n if (!isData && !isSnapshot) {\n diagnose({ kind: \"malformed_message\", detail: `channel ${header.channel} is not client-bound` });\n return;\n }\n if (isData) {\n if (s.expectSeq !== null && header.seq !== s.expectSeq) {\n diagnose({ kind: \"seq_gap\", id: s.id, expected: s.expectSeq, received: header.seq });\n }\n s.expectSeq = header.seq + 1;\n }\n // Copy: the payload is a view into a buffer the transport may reuse.\n const bytes = payload.slice();\n const handler = isData ? s.handlers.onData : s.handlers.onSnapshot;\n s.chain = s.chain.then(async () => {\n if (s.ended) return;\n try {\n await handler?.(bytes, header);\n } catch (error) {\n diagnose({ kind: \"handler_threw\", where: isData ? \"onData\" : \"onSnapshot\", error });\n }\n if (isData) s.lastSeq = header.seq;\n grantCredit(s, bytes.byteLength);\n });\n }\n\n function grantCredit(s: StreamState, consumed: number): void {\n s.consumedUncredited += consumed;\n // Batch: one credit per quarter window keeps the pipe full without a message per frame.\n if (s.consumedUncredited >= Math.max(1, Math.floor(s.windowBytes / 4))) {\n if (sendJson({ type: \"credit\", id: s.id, n: s.consumedUncredited })) s.consumedUncredited = 0;\n }\n }\n\n function flushSend(s: StreamState): void {\n if (s.sid === null || !socket || socket.readyState !== WS_OPEN) return;\n const maxPayload = state.welcome?.limits.max_frame_payload_bytes ?? DEFAULT_MAX_FRAME_PAYLOAD_BYTES;\n while (s.sendQueue.length > 0 && s.sendWindow > 0) {\n const head = s.sendQueue[0]!;\n const n = Math.min(head.byteLength, s.sendWindow, maxPayload);\n const chunk = head.subarray(0, n);\n if (n === head.byteLength) s.sendQueue.shift();\n else s.sendQueue[0] = head.subarray(n);\n s.sendWindow -= n;\n s.sendSeq += 1;\n socket.send(encodeFrame({ version: FRAME_VERSION, flags: 0, channel: FrameChannel.STDIN, cid: 0, sid: s.sid, seq: s.sendSeq }, chunk));\n }\n }\n\n function clearFirstFrame(s: StreamState): void {\n if (s.firstFrameTimer === null) return;\n timers.clearTimeout(s.firstFrameTimer);\n s.firstFrameTimer = null;\n }\n\n /**\n * A stream request that hears nothing within its deadline ends with a retryable TIMEOUT — never\n * an open-ended wait (a request lost behind a dead device socket cost 15- and 25-minute hangs) —\n * and the socket is probed: a dead one reconnects with the backoff, a live one stays.\n */\n function armFirstFrame(s: StreamState): void {\n clearFirstFrame(s);\n const waitMs = s.options.firstFrameMs ?? firstFrameMs;\n const id = s.id;\n s.firstFrameTimer = timers.setTimeout(() => {\n s.firstFrameTimer = null;\n if (s.ended || s.id !== id) return;\n diagnose({ kind: \"first_frame_timeout\", id, op: s.op, waitedMs: waitMs });\n streams.delete(id);\n if (s.sid !== null) bySid.delete(s.sid);\n abandon(id);\n endStream(s, null, new DesktopProtocolError(\"TIMEOUT\", `${s.op}: no answer within ${waitMs} ms`, { retryable: true }));\n wake();\n }, waitMs);\n }\n\n function endStream(s: StreamState, reason: EndReason | null, error: DesktopProtocolError | null): void {\n if (s.ended) return;\n clearFirstFrame(s);\n s.ended = true;\n s.sendQueue = [];\n if (!s.resultSettled) {\n s.resultSettled = true;\n s.rejectResult(error ?? new DesktopProtocolError(\"INTERNAL\", \"Stream ended before its result\"));\n }\n if (error) s.rejectDone(error);\n else s.resolveDone(reason ?? \"completed\");\n }\n\n function reattach(s: StreamState, welcome: Welcome): void {\n const id = newId(\"a\");\n streams.delete(s.id);\n s.id = id;\n s.reattaching = true;\n s.expectSeq = s.lastSeq > 0 ? s.lastSeq + 1 : null;\n s.consumedUncredited = 0;\n s.sendWindow = welcome.limits.default_window_bytes;\n s.sendSeq = 0;\n streams.set(id, s);\n const params: Record<string, unknown> = { resource_id: s.resourceId, mode: s.options.mode ?? \"control\" };\n if (s.lastSeq > 0) params.since_seq = s.lastSeq;\n if (s.options.windowBytes !== undefined) params.window_bytes = s.options.windowBytes;\n if (sendJson({ id, type: \"request\", cap: \"session\", op: \"attach\", params })) armFirstFrame(s);\n }\n\n function safeCall(where: string, fn: () => void): void {\n try {\n fn();\n } catch (error) {\n diagnose({ kind: \"handler_threw\", where, error });\n }\n }\n\n // ── public API ─────────────────────────────────────────────────────────────\n\n function ready(opts: RequestOptions = {}): Promise<Welcome> {\n if (state.status === \"open\" && state.welcome) return Promise.resolve(state.welcome);\n if (state.status === \"closed\") {\n return Promise.reject(state.lastError ?? new DesktopProtocolError(\"CANCELLED\", \"Client is closed\"));\n }\n if (state.status === \"idle\") connect();\n return new Promise((resolve, reject) => {\n const waiter = {\n resolve: (w: Welcome) => {\n done();\n resolve(w);\n },\n reject: (e: DesktopProtocolError) => {\n done();\n reject(e);\n },\n };\n const timeoutMs = opts.timeoutMs ?? requestTimeoutMs;\n const timer = timers.setTimeout(() => waiter.reject(new DesktopProtocolError(\"DEVICE_OFFLINE\", \"Device not reachable\", { retryable: true })), timeoutMs);\n const onAbort = () => waiter.reject(new DesktopProtocolError(\"CANCELLED\", \"Aborted\"));\n opts.signal?.addEventListener(\"abort\", onAbort, { once: true });\n function done() {\n readyWaiters.delete(waiter);\n timers.clearTimeout(timer);\n opts.signal?.removeEventListener(\"abort\", onAbort);\n }\n readyWaiters.add(waiter);\n });\n }\n\n async function request<N extends OpName>(op: N, params: OpParams<N>, opts: RequestOptions = {}): Promise<OpResult<N>> {\n if (OPS[op].kind !== \"unary\") {\n throw new DesktopProtocolError(\"INVALID_PARAMS\", `${op} is a ${OPS[op].kind} op — use stream()`);\n }\n await ready(opts);\n const id = newId(\"r\");\n if (opts.onRequestId) safeCall(\"onRequestId\", () => opts.onRequestId?.(id));\n return new Promise<OpResult<N>>((resolve, reject) => {\n const timeoutMs = opts.timeoutMs ?? requestTimeoutMs;\n const timer = timers.setTimeout(() => {\n pending.delete(id);\n cleanup();\n abandon(id);\n reject(new DesktopProtocolError(\"TIMEOUT\", `${op} timed out`, { retryable: true }));\n }, timeoutMs);\n const onAbort = () => {\n pending.delete(id);\n cleanup();\n abandon(id);\n reject(new DesktopProtocolError(\"CANCELLED\", \"Aborted\"));\n };\n function cleanup() {\n timers.clearTimeout(timer);\n opts.signal?.removeEventListener(\"abort\", onAbort);\n }\n opts.signal?.addEventListener(\"abort\", onAbort, { once: true });\n pending.set(id, { kind: \"unary\", op, resolve: resolve as (v: unknown) => void, reject, cleanup });\n if (!sendJson({ id, type: \"request\", ...capOf(op), params })) {\n pending.delete(id);\n cleanup();\n reject(new DesktopProtocolError(\"DEVICE_OFFLINE\", \"Connection lost\", { retryable: true }));\n }\n });\n }\n\n function stream<N extends StreamOpName>(\n op: N,\n params: OpParams<N>,\n handlers: StreamHandlers = {},\n opts: StreamOptions = {},\n ): DesktopStream<N> {\n let resolveResult!: (v: unknown) => void;\n let rejectResult!: (e: DesktopProtocolError) => void;\n let resolveDone!: (r: EndReason) => void;\n let rejectDone!: (e: DesktopProtocolError) => void;\n const result = new Promise<OpResult<N>>((res, rej) => {\n resolveResult = res as (v: unknown) => void;\n rejectResult = rej;\n });\n const done = new Promise<EndReason>((res, rej) => {\n resolveDone = res;\n rejectDone = rej;\n });\n // Consumers often await only one of the two; never leave the other as an unhandled rejection.\n result.catch(() => undefined);\n done.catch(() => undefined);\n\n // A caller-started session.attach (a page reload reattaching by the resource id it kept in its\n // URL) is a resource stream from its first byte: it survives drops like the stream that created\n // the resource, and its sequence continues from since_seq rather than from 1.\n const attach = op === \"session.attach\" ? (params as { resource_id: string; since_seq?: number }) : null;\n const s: StreamState = {\n op,\n handlers,\n options: opts,\n id: newId(\"s\"),\n sid: null,\n resourceId: attach ? attach.resource_id : null,\n lastSeq: attach?.since_seq ?? 0,\n expectSeq: attach ? (attach.since_seq === undefined ? null : attach.since_seq + 1) : 1,\n windowBytes: opts.windowBytes ?? DEFAULT_WINDOW_BYTES,\n consumedUncredited: 0,\n sendWindow: DEFAULT_WINDOW_BYTES,\n sendSeq: 0,\n sendQueue: [],\n chain: Promise.resolve(),\n resultSettled: false,\n resolveResult,\n rejectResult,\n resolveDone,\n rejectDone,\n ended: false,\n reattaching: false,\n firstFrameTimer: null,\n };\n\n const start = async () => {\n let welcome: Welcome;\n try {\n welcome = await ready(opts);\n } catch (error) {\n endStream(s, null, error as DesktopProtocolError);\n return;\n }\n if (s.ended) return;\n s.sendWindow = welcome.limits.default_window_bytes;\n if (opts.windowBytes === undefined) s.windowBytes = welcome.limits.default_window_bytes;\n streams.set(s.id, s);\n const wire: Record<string, unknown> = { ...(params as Record<string, unknown>) };\n if (opts.windowBytes !== undefined && \"window_bytes\" in OPS[op].params.shape) wire.window_bytes = opts.windowBytes;\n if (!sendJson({ id: s.id, type: \"request\", ...capOf(op), params: wire })) {\n streams.delete(s.id);\n endStream(s, null, new DesktopProtocolError(\"DEVICE_OFFLINE\", \"Connection lost\", { retryable: true }));\n return;\n }\n armFirstFrame(s);\n };\n void start();\n opts.signal?.addEventListener(\"abort\", () => handle.cancel(), { once: true });\n\n const encoder = new TextEncoder();\n const handle: DesktopStream<N> = {\n get id() {\n return s.id;\n },\n result,\n done,\n get resourceId() {\n return s.resourceId;\n },\n get lastSeq() {\n return s.lastSeq;\n },\n write(data) {\n if (s.ended) throw new DesktopProtocolError(\"RESOURCE_GONE\", \"Stream has ended\");\n const bytes = typeof data === \"string\" ? encoder.encode(data) : data;\n if (bytes.byteLength === 0) return;\n s.sendQueue.push(bytes);\n flushSend(s);\n },\n cancel() {\n if (s.ended) return;\n if (!sendJson({ id: s.id, type: \"cancel\" })) {\n streams.delete(s.id);\n endStream(s, \"cancelled\", null);\n }\n },\n async detach() {\n if (s.ended) return;\n if (s.resourceId === null) throw new DesktopProtocolError(\"INVALID_PARAMS\", \"Only resource streams can be detached\");\n const resourceId = s.resourceId;\n streams.delete(s.id);\n if (s.sid !== null) bySid.delete(s.sid);\n endStream(s, \"detached\", null);\n await request(\"session.detach\", { resource_id: resourceId });\n },\n };\n return handle;\n }\n\n function on<E extends EventName>(name: E, handler: EventHandler<E>): () => void {\n let set = eventHandlers.get(name);\n if (!set) {\n set = new Set();\n eventHandlers.set(name, set);\n }\n set.add(handler as EventHandler<EventName>);\n return () => {\n set.delete(handler as EventHandler<EventName>);\n };\n }\n\n function reauth(token: string): void {\n sendJson({ type: \"relay\", op: \"reauth\", token });\n }\n\n function wake(opts: WakeOptions = {}): void {\n if (closedByUser || state.status === \"closed\") return;\n if (state.status === \"idle\" || state.status === \"reconnecting\") {\n connect(); // dial now; connect() cancels the scheduled backoff timer\n return;\n }\n if (state.status === \"connecting\" || !socket || probeTimer !== null) return;\n const generation = socketGeneration;\n const heardBefore = heardCount;\n try {\n socket.send(PING_TEXT);\n } catch {\n // A socket that cannot even send is dead: fall through to the probe verdict.\n }\n probeTimer = timers.setTimeout(() => {\n probeTimer = null;\n if (generation !== socketGeneration || !socket) return;\n if (heardCount > heardBefore) return; // answered: the socket is alive\n const silentMs = timers.now() - lastHeardAt;\n diagnose({ kind: \"heartbeat_timeout\", silentMs });\n reportClose(null, \"wake probe timeout\", false);\n const dead = socket;\n onSocketGone(generation, null, new DesktopProtocolError(\"TIMEOUT\", \"Connection went silent\", { retryable: true }));\n try {\n dead.close(CloseCode.NORMAL, \"wake probe timeout\");\n } catch {\n // already closing\n }\n if (state.status === \"reconnecting\") connect(); // the person is looking: no backoff wait\n }, opts.probeMs ?? 4000);\n }\n\n return {\n connect,\n close,\n getState: () => state,\n subscribe(listener) {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n },\n ready,\n request,\n stream,\n on,\n reauth,\n wake,\n };\n}\n\nexport { RECONNECT_ALARM_ATTEMPTS };\n","/**\n * Wire a client's wake() to the browser events that mean \"the person is back\": the page becomes\n * visible again (iOS Safari suspends a background tab's sockets), a back/forward-cache restore\n * (`pageshow` with persisted), and the network returning (`online`). Framework-free; the React\n * binding is `useDesktopWake` in `./react`.\n */\nimport type { DesktopClient, WakeOptions } from \"./types\";\n\n/** The subset of window/document the binding listens on — injectable for tests and non-DOM hosts. */\nexport interface WakeTargets {\n window: Pick<Window, \"addEventListener\" | \"removeEventListener\">;\n document: Pick<Document, \"addEventListener\" | \"removeEventListener\" | \"visibilityState\">;\n}\n\nexport function bindDesktopWake(client: Pick<DesktopClient, \"wake\">, options: WakeOptions & { targets?: WakeTargets } = {}): () => void {\n const targets: WakeTargets | null =\n options.targets ?? (typeof window !== \"undefined\" && typeof document !== \"undefined\" ? { window, document } : null);\n if (!targets) return () => undefined;\n const wakeOptions: WakeOptions = options.probeMs === undefined ? {} : { probeMs: options.probeMs };\n const onVisibility = () => {\n if (targets.document.visibilityState === \"visible\") client.wake(wakeOptions);\n };\n const onWake = () => client.wake(wakeOptions);\n targets.document.addEventListener(\"visibilitychange\", onVisibility);\n targets.window.addEventListener(\"pageshow\", onWake);\n targets.window.addEventListener(\"online\", onWake);\n targets.window.addEventListener(\"focus\", onWake);\n return () => {\n targets.document.removeEventListener(\"visibilitychange\", onVisibility);\n targets.window.removeEventListener(\"pageshow\", onWake);\n targets.window.removeEventListener(\"online\", onWake);\n targets.window.removeEventListener(\"focus\", onWake);\n };\n}\n","import { DesktopProtocolError } from \"../error\";\nimport type { MlProgress, ModelsTranscribeResult, TranscriptionModelId } from \"../schema/models\";\nimport type { DesktopClient } from \"./types\";\n\n/** fs.write carries at most 4 MiB of bytes (base64 in one message). */\nexport const DESKTOP_TRANSCRIBE_MAX_BYTES = 4 * 1024 * 1024;\n\nexport interface DesktopTranscriberOptions {\n /** Whisper size; omitted = the device's default. */\n model?: TranscriptionModelId;\n /** ISO 639-1; omitted = detect. */\n language?: string;\n /** Per call (first use installs the runtime and a model): default 15 minutes. */\n timeoutMs?: number;\n /** Progress for each call (install steps, then each segment as it is recognized). */\n onProgress?: (progress: MlProgress) => void;\n}\n\n/** What a transcription returns: the shape `@ai-matrx/browser-audio`'s TranscriptionTransport expects. */\nexport interface DesktopTranscript {\n text: string;\n language: string;\n duration: number;\n segments: Array<{ start: number; end: number; text: string }>;\n result: ModelsTranscribeResult;\n}\n\nexport interface DesktopTranscriber {\n /** Transcribe recorded audio on the device: written to its temp folder, transcribed, removed. */\n transcribe(file: Blob, signal?: AbortSignal): Promise<DesktopTranscript>;\n}\n\nconst EXT: Record<string, string> = {\n \"audio/webm\": \"webm\",\n \"audio/ogg\": \"ogg\",\n \"audio/mp4\": \"m4a\",\n \"audio/mpeg\": \"mp3\",\n \"audio/wav\": \"wav\",\n \"audio/x-wav\": \"wav\",\n \"video/webm\": \"webm\",\n \"video/mp4\": \"mp4\",\n};\n\nfunction base64(bytes: Uint8Array): string {\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 0x8000) binary += String.fromCharCode(...bytes.subarray(i, i + 0x8000));\n return btoa(binary);\n}\n\n/**\n * Speech to text on the person's own computer, from any surface connected to it (the app's\n * screen, the web app or the phone through the relay). Structurally a\n * `@ai-matrx/browser-audio` TranscriptionTransport, so every voice input on the platform can\n * transcribe locally: `new BrowserAudioKernel({ transport: createDesktopTranscriber(client) })`.\n *\n * Audio travels as one `fs.write` into the device's temp folder (at most 4 MiB; longer\n * recordings are chunked by the kernel), then `models.transcribe`, then `fs.delete` — every step\n * an ordinary op, so this works through every transport with no special path.\n */\nexport function createDesktopTranscriber(client: DesktopClient, options: DesktopTranscriberOptions = {}): DesktopTranscriber {\n let temp: Promise<string> | null = null;\n const tempDir = () => (temp ??= client.request(\"sysinfo.get\", {}).then((s) => s.paths.temp.replace(/\\/$/, \"\")));\n\n return {\n async transcribe(file, signal) {\n if (file.size > DESKTOP_TRANSCRIBE_MAX_BYTES) {\n throw new DesktopProtocolError(\"PAYLOAD_TOO_LARGE\", \"Recording is larger than 4 MB\", { retryable: false, data: { limit_bytes: DESKTOP_TRANSCRIBE_MAX_BYTES } });\n }\n const type = file.type.split(\";\")[0]?.trim() ?? \"\";\n const name = `matrx-transcribe-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}.${EXT[type] ?? \"webm\"}`;\n const path = `${await tempDir()}/${name}`;\n const bytes = new Uint8Array(await file.arrayBuffer());\n await client.request(\"fs.write\", { path, content: base64(bytes), encoding: \"base64\", mode: 0o600 }, signal ? { signal } : {});\n let requestId = \"\";\n const off = options.onProgress\n ? client.on(\"models.progress\", (payload) => {\n if (payload.request_id === requestId) options.onProgress?.(payload.progress);\n })\n : () => undefined;\n try {\n const result = await client.request(\n \"models.transcribe\",\n { path, ...(options.model ? { model: options.model } : {}), ...(options.language ? { language: options.language } : {}) },\n { timeoutMs: options.timeoutMs ?? 15 * 60_000, onRequestId: (id) => (requestId = id), ...(signal ? { signal } : {}) },\n );\n return {\n text: result.text,\n language: result.language,\n duration: result.duration_s,\n segments: result.segments.map((s) => ({ start: s.start_s, end: s.end_s, text: s.text })),\n result,\n };\n } finally {\n off();\n void client.request(\"fs.delete\", { path, to_trash: false }).catch(() => undefined);\n }\n },\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/react.d.cts
CHANGED
|
@@ -8614,6 +8614,8 @@ interface StreamOptions extends RequestOptions {
|
|
|
8614
8614
|
windowBytes?: number;
|
|
8615
8615
|
/** Reattach mode for resource streams. Default "control". */
|
|
8616
8616
|
mode?: "control" | "read_only";
|
|
8617
|
+
/** This stream's first-frame deadline (overrides the client's firstFrameMs). */
|
|
8618
|
+
firstFrameMs?: number;
|
|
8617
8619
|
}
|
|
8618
8620
|
interface DesktopStream<N extends StreamOpName> {
|
|
8619
8621
|
/** The CURRENT request id carrying this stream (changes on reattach). */
|
package/dist/react.d.ts
CHANGED
|
@@ -8614,6 +8614,8 @@ interface StreamOptions extends RequestOptions {
|
|
|
8614
8614
|
windowBytes?: number;
|
|
8615
8615
|
/** Reattach mode for resource streams. Default "control". */
|
|
8616
8616
|
mode?: "control" | "read_only";
|
|
8617
|
+
/** This stream's first-frame deadline (overrides the client's firstFrameMs). */
|
|
8618
|
+
firstFrameMs?: number;
|
|
8617
8619
|
}
|
|
8618
8620
|
interface DesktopStream<N extends StreamOpName> {
|
|
8619
8621
|
/** The CURRENT request id carrying this stream (changes on reattach). */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-matrx/desktop-protocol",
|
|
3
|
-
"version": "0.21.
|
|
3
|
+
"version": "0.21.80",
|
|
4
4
|
"description": "The one wire contract between Matrx 2 (the desktop app) and every client that drives it — phone, web app, extension, server: zod schemas for the envelope and every cap.op, the 16-byte binary frame codec, a reconnecting request/stream/credit/reattach client, React hooks, and a generated JSON Schema + Pydantic twin that CI keeps byte-identical.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -137,5 +137,5 @@
|
|
|
137
137
|
"test:watch": "vitest",
|
|
138
138
|
"verify:tarball": "node ./scripts/verify-tarball.mjs"
|
|
139
139
|
},
|
|
140
|
-
"gitHead": "
|
|
140
|
+
"gitHead": "268d0c2f1f0b2ea129ee132098cb3e7b9184a2ab"
|
|
141
141
|
}
|