@ai-matrx/desktop-protocol 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +25 -0
- package/dist/client.cjs +47 -13
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +4 -2
- package/dist/client.d.ts +4 -2
- package/dist/client.js +47 -13
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +57 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -6
- package/dist/index.d.ts +29 -6
- package/dist/index.js +57 -2
- package/dist/index.js.map +1 -1
- package/dist/react.d.cts +20 -1
- package/dist/react.d.ts +20 -1
- package/dist/{registry-BeY9D7h0.d.cts → registry-Duc_VFN8.d.cts} +93 -3
- package/dist/{registry-BeY9D7h0.d.ts → registry-Duc_VFN8.d.ts} +93 -3
- package/package.json +1 -1
package/dist/client.d.cts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { BackoffOptions } from '@ai-matrx/realtime';
|
|
2
2
|
export { RECONNECT_ALARM_ATTEMPTS } from '@ai-matrx/realtime';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { W as Welcome, D as DesktopProtocolError, O as OpName, a as OpParams, b as OpResult, c as OPS, S as StreamMeta, E as EndReason, d as EVENTS,
|
|
5
|
-
export { i as isDesktopProtocolError } from './registry-
|
|
4
|
+
import { W as Welcome, D as DesktopProtocolError, C as CloseOutcome, O as OpName, a as OpParams, b as OpResult, c as OPS, S as StreamMeta, E as EndReason, d as EVENTS, e as ClientType } from './registry-Duc_VFN8.cjs';
|
|
5
|
+
export { i as isDesktopProtocolError } from './registry-Duc_VFN8.cjs';
|
|
6
6
|
import { FrameHeader } from './frame.cjs';
|
|
7
7
|
|
|
8
8
|
/** The subset of the WHATWG WebSocket the client uses — browser, React Native, `ws` and Workers all fit. */
|
|
@@ -49,6 +49,8 @@ interface DesktopClientState {
|
|
|
49
49
|
retryInMs: number | null;
|
|
50
50
|
lastError: DesktopProtocolError | null;
|
|
51
51
|
lastCloseCode: number | null;
|
|
52
|
+
/** Why dialing stopped, when the far side refused us for good (CLOSE_RULES); null otherwise. */
|
|
53
|
+
outcome: CloseOutcome | null;
|
|
52
54
|
}
|
|
53
55
|
type DesktopClientDiagnostic = {
|
|
54
56
|
kind: "malformed_message";
|
package/dist/client.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { BackoffOptions } from '@ai-matrx/realtime';
|
|
2
2
|
export { RECONNECT_ALARM_ATTEMPTS } from '@ai-matrx/realtime';
|
|
3
3
|
import { z } from 'zod';
|
|
4
|
-
import { W as Welcome, D as DesktopProtocolError, O as OpName, a as OpParams, b as OpResult, c as OPS, S as StreamMeta, E as EndReason, d as EVENTS,
|
|
5
|
-
export { i as isDesktopProtocolError } from './registry-
|
|
4
|
+
import { W as Welcome, D as DesktopProtocolError, C as CloseOutcome, O as OpName, a as OpParams, b as OpResult, c as OPS, S as StreamMeta, E as EndReason, d as EVENTS, e as ClientType } from './registry-Duc_VFN8.js';
|
|
5
|
+
export { i as isDesktopProtocolError } from './registry-Duc_VFN8.js';
|
|
6
6
|
import { FrameHeader } from './frame.js';
|
|
7
7
|
|
|
8
8
|
/** The subset of the WHATWG WebSocket the client uses — browser, React Native, `ws` and Workers all fit. */
|
|
@@ -49,6 +49,8 @@ interface DesktopClientState {
|
|
|
49
49
|
retryInMs: number | null;
|
|
50
50
|
lastError: DesktopProtocolError | null;
|
|
51
51
|
lastCloseCode: number | null;
|
|
52
|
+
/** Why dialing stopped, when the far side refused us for good (CLOSE_RULES); null otherwise. */
|
|
53
|
+
outcome: CloseOutcome | null;
|
|
52
54
|
}
|
|
53
55
|
type DesktopClientDiagnostic = {
|
|
54
56
|
kind: "malformed_message";
|
package/dist/client.js
CHANGED
|
@@ -281,6 +281,29 @@ var CloseCode = {
|
|
|
281
281
|
};
|
|
282
282
|
var CloseCodeValue = z3.literal([1e3, 1001, 1006, 1012, 1013, 4001, 4003, 4004, 4008, 4009, 4010, 4400, 4426]);
|
|
283
283
|
|
|
284
|
+
// src/close-policy.ts
|
|
285
|
+
var CLOSE_RULES = {
|
|
286
|
+
[CloseCode.NORMAL]: { action: "reconnect", error: ["DEVICE_OFFLINE", "Connection closed"] },
|
|
287
|
+
[CloseCode.GOING_AWAY]: { action: "reconnect_now", error: ["DEVICE_OFFLINE", "Connection lost"] },
|
|
288
|
+
[CloseCode.ABNORMAL]: { action: "reconnect_now", error: ["DEVICE_OFFLINE", "Connection lost"] },
|
|
289
|
+
[CloseCode.DEVICE_RECONNECTED]: { action: "reconnect_now", error: ["DEVICE_OFFLINE", "Device reconnected"] },
|
|
290
|
+
[CloseCode.TRY_AGAIN_LATER]: { action: "reconnect", error: ["DEVICE_OFFLINE", "Relay busy; retrying"] },
|
|
291
|
+
[CloseCode.AUTH_INVALID]: { action: "reauth", outcome: "signed_out", error: ["AUTH_INVALID", "Sign-in was not accepted"] },
|
|
292
|
+
[CloseCode.AUTH_FORBIDDEN]: { action: "stop", outcome: "not_owned", error: ["AUTH_FORBIDDEN", "Not this device's owner"] },
|
|
293
|
+
[CloseCode.DEVICE_NOT_FOUND]: { action: "stop", outcome: "removed", error: ["NOT_FOUND", "Device not found"] },
|
|
294
|
+
[CloseCode.AUTH_EXPIRED]: { action: "reauth", outcome: "signed_out", error: ["AUTH_EXPIRED", "Sign-in expired"] },
|
|
295
|
+
[CloseCode.REPLACED]: { action: "stop", outcome: "replaced", error: ["CONFLICT", "Replaced by a newer connection"] },
|
|
296
|
+
[CloseCode.DEVICE_REVOKED]: { action: "stop", outcome: "revoked", error: ["AUTH_DEVICE_REVOKED", "This device was revoked"] },
|
|
297
|
+
// A malformed message, or a connection the relay lost track of: a fresh socket starts clean.
|
|
298
|
+
[CloseCode.PROTOCOL_ERROR]: { action: "reconnect", error: ["PROTOCOL_ERROR", "Connection reset by the relay"] },
|
|
299
|
+
[CloseCode.UPGRADE_REQUIRED]: { action: "stop", outcome: "upgrade_required", error: ["PROTOCOL_VERSION_UNSUPPORTED", "Protocol upgrade required"] }
|
|
300
|
+
};
|
|
301
|
+
var UNKNOWN = { action: "reconnect", error: ["DEVICE_OFFLINE", "Connection lost"] };
|
|
302
|
+
function closeRule(code) {
|
|
303
|
+
if (code === null || code === void 0) return CLOSE_RULES[CloseCode.ABNORMAL];
|
|
304
|
+
return CLOSE_RULES[code] ?? UNKNOWN;
|
|
305
|
+
}
|
|
306
|
+
|
|
284
307
|
// src/schema/frame.ts
|
|
285
308
|
import { z as z4 } from "zod";
|
|
286
309
|
var FrameHeader = z4.strictObject({
|
|
@@ -616,7 +639,11 @@ var SessionControlChangedEvent = z8.strictObject({ controller_client_id: z8.stri
|
|
|
616
639
|
import { z as z9 } from "zod";
|
|
617
640
|
var RelayDeviceStatusEvent = z9.strictObject({
|
|
618
641
|
online: z9.boolean(),
|
|
619
|
-
|
|
642
|
+
/**
|
|
643
|
+
* When the device last went online/offline; null = it has never connected (since 1.1 —
|
|
644
|
+
* NULL_SINCE: a 1.0 reader is sent 0, its old meaning).
|
|
645
|
+
*/
|
|
646
|
+
since_ms: epochMs.nullable(),
|
|
620
647
|
app_version: z9.string().max(32).nullable(),
|
|
621
648
|
protocol_version: ProtocolVersion.nullable()
|
|
622
649
|
});
|
|
@@ -698,13 +725,6 @@ var EVENTS = {
|
|
|
698
725
|
|
|
699
726
|
// src/client/client.ts
|
|
700
727
|
var WS_OPEN = 1;
|
|
701
|
-
var TERMINAL_CLOSE = /* @__PURE__ */ new Map([
|
|
702
|
-
[CloseCode.DEVICE_REVOKED, ["AUTH_DEVICE_REVOKED", "This device was revoked"]],
|
|
703
|
-
[CloseCode.AUTH_FORBIDDEN, ["AUTH_FORBIDDEN", "Not this device's owner"]],
|
|
704
|
-
[CloseCode.DEVICE_NOT_FOUND, ["NOT_FOUND", "Device not found"]],
|
|
705
|
-
[CloseCode.REPLACED, ["CONFLICT", "Replaced by a newer connection"]],
|
|
706
|
-
[CloseCode.UPGRADE_REQUIRED, ["PROTOCOL_VERSION_UNSUPPORTED", "Protocol upgrade required"]]
|
|
707
|
-
]);
|
|
708
728
|
var defaultTimers = {
|
|
709
729
|
setTimeout: (fn, ms) => globalThis.setTimeout(fn, ms),
|
|
710
730
|
clearTimeout: (handle) => globalThis.clearTimeout(handle),
|
|
@@ -747,8 +767,10 @@ function createDesktopClient(options) {
|
|
|
747
767
|
attempts: 0,
|
|
748
768
|
retryInMs: null,
|
|
749
769
|
lastError: null,
|
|
750
|
-
lastCloseCode: null
|
|
770
|
+
lastCloseCode: null,
|
|
771
|
+
outcome: null
|
|
751
772
|
};
|
|
773
|
+
let authRefusals = 0;
|
|
752
774
|
const listeners = /* @__PURE__ */ new Set();
|
|
753
775
|
const readyWaiters = /* @__PURE__ */ new Set();
|
|
754
776
|
const pending = /* @__PURE__ */ new Map();
|
|
@@ -783,6 +805,7 @@ function createDesktopClient(options) {
|
|
|
783
805
|
}
|
|
784
806
|
function connect() {
|
|
785
807
|
if (state.status === "connecting" || state.status === "handshaking" || state.status === "open") return;
|
|
808
|
+
if (state.status === "closed" || state.status === "idle") authRefusals = 0;
|
|
786
809
|
closedByUser = false;
|
|
787
810
|
if (reconnectTimer !== null) {
|
|
788
811
|
timers.clearTimeout(reconnectTimer);
|
|
@@ -864,8 +887,11 @@ function createDesktopClient(options) {
|
|
|
864
887
|
timers.clearTimeout(probeTimer);
|
|
865
888
|
probeTimer = null;
|
|
866
889
|
}
|
|
867
|
-
const
|
|
868
|
-
|
|
890
|
+
const rule = code === null ? null : closeRule(code);
|
|
891
|
+
if (rule?.action === "reauth") authRefusals++;
|
|
892
|
+
const stopped = rule !== null && (rule.action === "stop" || rule.action === "reauth" && authRefusals >= 2);
|
|
893
|
+
const terminal = stopped && rule ? rule : void 0;
|
|
894
|
+
const lost = error ?? (terminal ? new DesktopProtocolError(terminal.error[0], terminal.error[1]) : rule && rule.action === "reauth" ? new DesktopProtocolError(rule.error[0], rule.error[1], { retryable: true }) : new DesktopProtocolError("DEVICE_OFFLINE", "Connection lost", { retryable: true }));
|
|
869
895
|
for (const [id, p] of pending) {
|
|
870
896
|
pending.delete(id);
|
|
871
897
|
p.cleanup();
|
|
@@ -882,7 +908,14 @@ function createDesktopClient(options) {
|
|
|
882
908
|
endStream(s, null, lost);
|
|
883
909
|
}
|
|
884
910
|
if (closedByUser || terminal) {
|
|
885
|
-
setState({
|
|
911
|
+
setState({
|
|
912
|
+
status: "closed",
|
|
913
|
+
welcome: null,
|
|
914
|
+
lastError: closedByUser ? state.lastError : lost,
|
|
915
|
+
lastCloseCode: code,
|
|
916
|
+
retryInMs: null,
|
|
917
|
+
outcome: closedByUser ? null : terminal?.outcome ?? null
|
|
918
|
+
});
|
|
886
919
|
rejectReadyWaiters(lost);
|
|
887
920
|
return;
|
|
888
921
|
}
|
|
@@ -1036,7 +1069,8 @@ function createDesktopClient(options) {
|
|
|
1036
1069
|
}
|
|
1037
1070
|
helloId = null;
|
|
1038
1071
|
backoff.markConnected();
|
|
1039
|
-
|
|
1072
|
+
authRefusals = 0;
|
|
1073
|
+
setState({ status: "open", welcome: welcome.data, attempts: 0, retryInMs: null, lastError: null, outcome: null });
|
|
1040
1074
|
for (const w of [...readyWaiters]) {
|
|
1041
1075
|
readyWaiters.delete(w);
|
|
1042
1076
|
w.resolve(welcome.data);
|