@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 CHANGED
@@ -1,10 +1,21 @@
1
1
  # Changelog
2
2
 
3
- ## 0.21.79
3
+ ## 0.21.80
4
4
 
5
5
  UNVERIFIED: this release has no Unreleased entry and the source comparison could not be made (the caller supplied no source comparison). Whether source changed is unknown; consumer action is unknown.
6
6
  Check the package's gitHead on npm against this version's gitHead: `git diff <previous gitHead> <this gitHead> -- apps/shared/desktop-protocol/src`.
7
7
 
8
+ ## 0.21.79
9
+
10
+ SOURCE CHANGED WITH NO RELEASE NOTE. This release shipped source changes that nobody described in an Unreleased entry,
11
+ so they may include breaking API changes. Consumer action is UNKNOWN: read the diff before upgrading.
12
+ Diff: `git diff dc95f05a68 e6fc2655c1 -- apps/shared/desktop-protocol/src`
13
+
14
+ Changed shipped source files (3):
15
+ - `apps/shared/desktop-protocol/src/contract.ts`
16
+ - `apps/shared/desktop-protocol/src/schema/coding.ts`
17
+ - `apps/shared/desktop-protocol/src/schema/primitives.ts`
18
+
8
19
  ## 0.21.78
9
20
 
10
21
  SOURCE CHANGED WITH NO RELEASE NOTE. This release shipped source changes that nobody described in an Unreleased entry,
package/dist/client.cjs CHANGED
@@ -5206,6 +5206,7 @@ function createDesktopClient(options) {
5206
5206
  const makeSocket = options.webSocket ?? defaultWebSocket();
5207
5207
  const heartbeatMs = options.heartbeatMs ?? 25e3;
5208
5208
  const requestTimeoutMs = options.requestTimeoutMs ?? 7e4;
5209
+ const firstFrameMs = options.firstFrameMs ?? requestTimeoutMs;
5209
5210
  const protocolVersion = options.protocolVersion ?? `${PROTOCOL_MAJOR}.${PROTOCOL_MINOR}`;
5210
5211
  const backoff = (0, import_realtime.createBackoff)({ ...options.backoff, now: timers.now });
5211
5212
  const diagnose = options.onDiagnostic ?? ((d) => {
@@ -5243,6 +5244,7 @@ function createDesktopClient(options) {
5243
5244
  let probeTimer = null;
5244
5245
  let lastHeardAt = 0;
5245
5246
  let heardCount = 0;
5247
+ let pongs = 0;
5246
5248
  let closedByUser = false;
5247
5249
  const newId = (prefix) => `${prefix}${(++nextId).toString(36)}`;
5248
5250
  function setState(patch) {
@@ -5290,6 +5292,7 @@ function createDesktopClient(options) {
5290
5292
  ws.onopen = () => {
5291
5293
  if (generation !== socketGeneration) return;
5292
5294
  lastHeardAt = timers.now();
5295
+ pongs = 0;
5293
5296
  helloId = newId("h");
5294
5297
  setState({ status: "handshaking" });
5295
5298
  sendJson({ type: "hello", id: helloId, protocolVersion, clientType: options.clientType, clientVersion: options.clientVersion });
@@ -5305,6 +5308,8 @@ function createDesktopClient(options) {
5305
5308
  };
5306
5309
  ws.onclose = (event) => {
5307
5310
  if (generation !== socketGeneration) return;
5311
+ const ev = event;
5312
+ reportClose(ev.code, ev.reason ?? "", ev.wasClean ?? false);
5308
5313
  onSocketGone(generation, event.code, null);
5309
5314
  };
5310
5315
  }
@@ -5316,6 +5321,7 @@ function createDesktopClient(options) {
5316
5321
  const silentMs = timers.now() - lastHeardAt;
5317
5322
  if (silentMs >= heartbeatMs * 2) {
5318
5323
  diagnose({ kind: "heartbeat_timeout", silentMs });
5324
+ reportClose(null, "heartbeat timeout", false);
5319
5325
  const dead = socket;
5320
5326
  onSocketGone(generation, null, new DesktopProtocolError("TIMEOUT", "Connection went silent", { retryable: true }));
5321
5327
  try {
@@ -5328,6 +5334,9 @@ function createDesktopClient(options) {
5328
5334
  scheduleHeartbeat(generation);
5329
5335
  }, heartbeatMs);
5330
5336
  }
5337
+ function reportClose(code, reason, wasClean) {
5338
+ diagnose({ kind: "socket_closed", code, reason: reason.slice(0, 120), wasClean, idleSinceLastRxMs: Math.max(0, timers.now() - lastHeardAt), pongs });
5339
+ }
5331
5340
  function onSocketGone(generation, code, error) {
5332
5341
  if (generation !== socketGeneration) return;
5333
5342
  socketGeneration++;
@@ -5416,7 +5425,10 @@ function createDesktopClient(options) {
5416
5425
  }
5417
5426
  function onMessage(data) {
5418
5427
  if (typeof data === "string") {
5419
- if (data === PONG_TEXT) return;
5428
+ if (data === PONG_TEXT) {
5429
+ pongs++;
5430
+ return;
5431
+ }
5420
5432
  let json;
5421
5433
  try {
5422
5434
  json = JSON.parse(data);
@@ -5447,6 +5459,10 @@ function createDesktopClient(options) {
5447
5459
  onFrame(frame.header, frame.payload);
5448
5460
  }
5449
5461
  function onEnvelope(msg) {
5462
+ if (msg.type !== "event") {
5463
+ const heard = streams.get(msg.id);
5464
+ if (heard) clearFirstFrame(heard);
5465
+ }
5450
5466
  switch (msg.type) {
5451
5467
  case "response": {
5452
5468
  if (msg.id === helloId) return onWelcome(msg.result);
@@ -5588,6 +5604,7 @@ function createDesktopClient(options) {
5588
5604
  diagnose({ kind: "unknown_stream", sid: header.sid });
5589
5605
  return;
5590
5606
  }
5607
+ clearFirstFrame(s);
5591
5608
  const isData = header.channel === FrameChannel.DATA || header.channel === FrameChannel.STDERR;
5592
5609
  const isSnapshot = header.channel === FrameChannel.SNAPSHOT;
5593
5610
  if (!isData && !isSnapshot) {
@@ -5633,8 +5650,29 @@ function createDesktopClient(options) {
5633
5650
  socket.send(encodeFrame({ version: FRAME_VERSION, flags: 0, channel: FrameChannel.STDIN, cid: 0, sid: s.sid, seq: s.sendSeq }, chunk));
5634
5651
  }
5635
5652
  }
5653
+ function clearFirstFrame(s) {
5654
+ if (s.firstFrameTimer === null) return;
5655
+ timers.clearTimeout(s.firstFrameTimer);
5656
+ s.firstFrameTimer = null;
5657
+ }
5658
+ function armFirstFrame(s) {
5659
+ clearFirstFrame(s);
5660
+ const waitMs = s.options.firstFrameMs ?? firstFrameMs;
5661
+ const id = s.id;
5662
+ s.firstFrameTimer = timers.setTimeout(() => {
5663
+ s.firstFrameTimer = null;
5664
+ if (s.ended || s.id !== id) return;
5665
+ diagnose({ kind: "first_frame_timeout", id, op: s.op, waitedMs: waitMs });
5666
+ streams.delete(id);
5667
+ if (s.sid !== null) bySid.delete(s.sid);
5668
+ abandon(id);
5669
+ endStream(s, null, new DesktopProtocolError("TIMEOUT", `${s.op}: no answer within ${waitMs} ms`, { retryable: true }));
5670
+ wake();
5671
+ }, waitMs);
5672
+ }
5636
5673
  function endStream(s, reason, error) {
5637
5674
  if (s.ended) return;
5675
+ clearFirstFrame(s);
5638
5676
  s.ended = true;
5639
5677
  s.sendQueue = [];
5640
5678
  if (!s.resultSettled) {
@@ -5657,7 +5695,7 @@ function createDesktopClient(options) {
5657
5695
  const params = { resource_id: s.resourceId, mode: s.options.mode ?? "control" };
5658
5696
  if (s.lastSeq > 0) params.since_seq = s.lastSeq;
5659
5697
  if (s.options.windowBytes !== void 0) params.window_bytes = s.options.windowBytes;
5660
- sendJson({ id, type: "request", cap: "session", op: "attach", params });
5698
+ if (sendJson({ id, type: "request", cap: "session", op: "attach", params })) armFirstFrame(s);
5661
5699
  }
5662
5700
  function safeCall(where, fn) {
5663
5701
  try {
@@ -5766,7 +5804,8 @@ function createDesktopClient(options) {
5766
5804
  resolveDone,
5767
5805
  rejectDone,
5768
5806
  ended: false,
5769
- reattaching: false
5807
+ reattaching: false,
5808
+ firstFrameTimer: null
5770
5809
  };
5771
5810
  const start = async () => {
5772
5811
  let welcome;
@@ -5785,7 +5824,9 @@ function createDesktopClient(options) {
5785
5824
  if (!sendJson({ id: s.id, type: "request", ...capOf(op), params: wire })) {
5786
5825
  streams.delete(s.id);
5787
5826
  endStream(s, null, new DesktopProtocolError("DEVICE_OFFLINE", "Connection lost", { retryable: true }));
5827
+ return;
5788
5828
  }
5829
+ armFirstFrame(s);
5789
5830
  };
5790
5831
  void start();
5791
5832
  opts.signal?.addEventListener("abort", () => handle.cancel(), { once: true });
@@ -5861,6 +5902,7 @@ function createDesktopClient(options) {
5861
5902
  if (heardCount > heardBefore) return;
5862
5903
  const silentMs = timers.now() - lastHeardAt;
5863
5904
  diagnose({ kind: "heartbeat_timeout", silentMs });
5905
+ reportClose(null, "wake probe timeout", false);
5864
5906
  const dead = socket;
5865
5907
  onSocketGone(generation, null, new DesktopProtocolError("TIMEOUT", "Connection went silent", { retryable: true }));
5866
5908
  try {