@byokit/pair 0.10.1 → 0.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.10.2 (2026-10-17)
6
+
7
+ - FIX: a busy host that answers a ping late no longer has its live link dropped. `DeviceLink` now counts any pong up to the latest ping, a reply to one of its own waiting requests, or a frame on one of its own streams as hearing from the host, and counts silence from its first ping rather than from the connect, so a host that answers even that first ping late stays online. A host that goes silent is still dropped after two silent ping rounds (`2 × pingMs`, checked once a round). Host events and broadcasts alone still do not keep a link up: they show only that the host can talk, not that it hears the device, so only an answer to something the device sent proves the round trip.
8
+
5
9
  ## 0.10.1 (2026-10-16)
6
10
 
7
11
  - FIX: the browser pairing test opens the pairing page over the test browser's own private CDP pipe once Chromium answers there, not from the launch command line. On a slow first start Chromium's network service quits after 15 s unanswered and took the launch page's request with it, so the test silently sat out its 180 s deadline; the page now loads after Chromium restarts the service, and a page Chromium cannot open fails at once with Chromium's own navigation error.
package/dist/device.d.ts CHANGED
@@ -150,6 +150,9 @@ export declare class DeviceLink {
150
150
  * A tick that fires long after it was due means this device's own timers were frozen (an app in the background,
151
151
  * a hidden tab), not that the host went quiet: no ping went out, so none came back. */
152
152
  private ping;
153
+ /** Whether `m` answers something this device sent: any pong so far (a busy host answers late), a reply to a waiting
154
+ * request, or a frame on one of its streams. Only those prove the host hears this device; its events alone do not. */
155
+ private answers;
153
156
  private sendPending;
154
157
  private settle;
155
158
  private again;
package/dist/device.js CHANGED
@@ -320,7 +320,7 @@ export class DeviceLink {
320
320
  let active;
321
321
  const l = await dial(url, keyPairFrom(unb64url(secret)), { key: unb64url(this.grant.host) }, { t: 'auth', session: this.session, ack: this.ack, fresh: this.fresh }, this.o, {
322
322
  message: (m) => { if (this.conn === active) {
323
- if (m.t === 'pong' && m.n === this.pingId)
323
+ if (this.answers(m))
324
324
  this.heard = Date.now();
325
325
  this.message(m);
326
326
  } },
@@ -396,8 +396,9 @@ export class DeviceLink {
396
396
  if (this.conn !== l)
397
397
  return;
398
398
  const now = Date.now();
399
- // Count the silence from now; a socket that is really dead still misses the pings that follow.
400
- if (now - due > every / 2)
399
+ // Count the silence from now; a socket that is really dead still misses the pings that follow. Before the first
400
+ // ping nothing was asked, so a host that answers it late is not silent either.
401
+ if (now - due > every / 2 || !this.pingId)
401
402
  this.heard = now;
402
403
  else if (now - this.heard > 2 * every) {
403
404
  l.close();
@@ -412,6 +413,11 @@ export class DeviceLink {
412
413
  };
413
414
  later(every, tick);
414
415
  }
416
+ /** Whether `m` answers something this device sent: any pong so far (a busy host answers late), a reply to a waiting
417
+ * request, or a frame on one of its streams. Only those prove the host hears this device; its events alone do not. */
418
+ answers(m) {
419
+ return (m.t === 'pong' && m.n <= this.pingId) || (m.t === 'res' && this.pending.has(m.id)) || !!this.streams?.has(m.s);
420
+ }
415
421
  sendPending(l, id, p) {
416
422
  try {
417
423
  l.send(p.msg);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byokit/pair",
3
- "version": "0.10.1",
3
+ "version": "0.10.2",
4
4
  "description": "Scan a code to pair a phone or browser with the home computer over one encrypted link (Noise IK over WebSocket).",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",