@hellolynk-ai/openclaw-channel 0.2.107 → 0.2.108

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.
@@ -387,7 +387,9 @@ export async function issueDeviceRuntimeSession(options) {
387
387
  }
388
388
  return fresh;
389
389
  }
390
- throw new HelloLynkClientError(safeDeviceRuntimeErrorCode(result?.error), {
390
+ const code = response.status === 401 && result?.error === "device_credential_invalid"
391
+ && result?.reason === "device_credential_revoked" ? result.reason : safeDeviceRuntimeErrorCode(result?.error);
392
+ throw new HelloLynkClientError(code, {
391
393
  httpStatus: response.status,
392
394
  retryable: response.status === 408 || response.status === 425 || response.status === 429 || response.status >= 500,
393
395
  });
@@ -584,6 +586,7 @@ export function createDeviceRuntimeSessionManager(options = {}) {
584
586
  );
585
587
  let current = null;
586
588
  let rejectedCredential = null;
589
+ const revokedFingerprints = new Set();
587
590
  let localIssueTail = Promise.resolve();
588
591
 
589
592
  const routeMatches = (session, input) => {
@@ -668,7 +671,15 @@ export function createDeviceRuntimeSessionManager(options = {}) {
668
671
  : null;
669
672
  // The production caller holds the existing session lock, including across
670
673
  // Host processes. An authority denial may drain the current Host.
674
+ const revocationKey = fingerprint && `revoked-${fingerprint}`;
671
675
  if (fingerprint) {
676
+ // An older process may update or clear its temporary rejection for the
677
+ // profile. Keep permanent revocation under the credential's own key.
678
+ if (revokedFingerprints.has(fingerprint)
679
+ || (await credentialRejections?.load(revocationKey).catch(() => null))?.fingerprint === fingerprint) {
680
+ revokedFingerprints.add(fingerprint);
681
+ throw new HelloLynkClientError("device_credential_revoked", { httpStatus: 401 });
682
+ }
672
683
  const isCoolingDown = (rejection) => {
673
684
  if (rejection?.fingerprint !== fingerprint) return false;
674
685
  const age = now() - rejection.rejectedAtMs;
@@ -685,10 +696,14 @@ export function createDeviceRuntimeSessionManager(options = {}) {
685
696
  try {
686
697
  session = reusable(await issue(request), input);
687
698
  } catch (error) {
688
- if (fingerprint && error?.httpStatus === 401 && error.code === "device_credential_invalid") {
689
- rejectedCredential = { fingerprint, rejectedAtMs: now() };
690
- // Preserve the authority denial even if local storage is unavailable.
691
- await credentialRejections?.save(sessionKey, rejectedCredential).catch(() => {});
699
+ if (fingerprint && error?.httpStatus === 401) {
700
+ if (error.code === "device_credential_revoked") {
701
+ revokedFingerprints.add(fingerprint);
702
+ await credentialRejections?.save(revocationKey, { fingerprint, rejectedAtMs: now() }).catch(() => {});
703
+ } else if (error.code === "device_credential_invalid") {
704
+ rejectedCredential = { fingerprint, rejectedAtMs: now() };
705
+ await credentialRejections?.save(sessionKey, rejectedCredential).catch(() => {});
706
+ }
692
707
  }
693
708
  throw error;
694
709
  }
@@ -35,7 +35,7 @@ export const HELLOLYNK_NEUTRAL_HOST_PROCESS_CONTRACT = "hellolynk-neutral-host-p
35
35
  export const HELLOLYNK_NEUTRAL_HOST_DISCOVERY_CONTRACT = "hellolynk-neutral-host-discovery-v1";
36
36
  // Raised with every release batch, together with the six client versions. A Host reports it
37
37
  // in its health; the higher release stays and the lower one makes room.
38
- export const HELLOLYNK_HOST_RELEASE_ORDINAL = 18;
38
+ export const HELLOLYNK_HOST_RELEASE_ORDINAL = 19;
39
39
 
40
40
  const INSTALLATION_LOCK_CONTRACT = "hellolynk-neutral-host-installation-lock-v2";
41
41
  const INSTALLATION_LOCK_MAX_BYTES = 4 * 1024;
@@ -2,7 +2,7 @@
2
2
  "contract": "hellolynk-client-npm-pack-manifest-v1",
3
3
  "client": "openclaw",
4
4
  "packageName": "@hellolynk-ai/openclaw-channel",
5
- "version": "0.2.107",
5
+ "version": "0.2.108",
6
6
  "workbench": {
7
7
  "path": "runtime/workbench/hellolynk-workbench-build.json",
8
8
  "contract": "hellolynk-shared-workbench-build-v1",
@@ -32,8 +32,8 @@
32
32
  },
33
33
  {
34
34
  "path": "clients/core/hellolynk-client-core.mjs",
35
- "bytes": 35808,
36
- "sha256": "dbab0f067c1a7f02c43b2696e1f5972288acd4f93a18684bf3cc120edff5cf94"
35
+ "bytes": 36715,
36
+ "sha256": "1fb8f11e78c0c26e74a4e76dbf295131b63ab6908e964c62e6452e31a694f67a"
37
37
  },
38
38
  {
39
39
  "path": "clients/core/hellolynk-client-profile.mjs",
@@ -233,7 +233,7 @@
233
233
  {
234
234
  "path": "clients/core/hellolynk-neutral-host-process.mjs",
235
235
  "bytes": 229709,
236
- "sha256": "34b985f75bc693954eb66bb788fc2814482bb8bf402f14b72ea2faf5f70cf4ea"
236
+ "sha256": "146cac23328760ae5e71e52b297ea6a7990972d3181b65209f308e0c3b579a1a"
237
237
  },
238
238
  {
239
239
  "path": "clients/core/hellolynk-neutral-host-store-adapters.mjs",
@@ -333,7 +333,7 @@
333
333
  {
334
334
  "path": "integrations/openclaw-channel/package.json",
335
335
  "bytes": 2158,
336
- "sha256": "7e7b9de94799afc84e7424499b5f814a88d0d0a75f4e38fa15c7b5defe5b5697"
336
+ "sha256": "88d81c1ccb9b025d151803e0666f34a9d28cbfdebdb9d5e66f5a4ba2f499b51b"
337
337
  },
338
338
  {
339
339
  "path": "integrations/openclaw-channel/setup-entry.mjs",
@@ -408,7 +408,7 @@
408
408
  {
409
409
  "path": "package.json",
410
410
  "bytes": 1985,
411
- "sha256": "12a95b2325ce7817c2b3308eec6e18fcd67738c9c8f4e62ed68b6d4c61f56309"
411
+ "sha256": "8d50b271d911cb33c1551c886c0a1abcf6c95c932b99556764ed81ace307d620"
412
412
  },
413
413
  {
414
414
  "path": "README.md",
@@ -432,8 +432,8 @@
432
432
  },
433
433
  {
434
434
  "path": "runtime/core/hellolynk-client-core.mjs",
435
- "bytes": 35808,
436
- "sha256": "dbab0f067c1a7f02c43b2696e1f5972288acd4f93a18684bf3cc120edff5cf94"
435
+ "bytes": 36715,
436
+ "sha256": "1fb8f11e78c0c26e74a4e76dbf295131b63ab6908e964c62e6452e31a694f67a"
437
437
  },
438
438
  {
439
439
  "path": "runtime/core/hellolynk-client-profile.mjs",
@@ -633,7 +633,7 @@
633
633
  {
634
634
  "path": "runtime/core/hellolynk-neutral-host-process.mjs",
635
635
  "bytes": 229709,
636
- "sha256": "34b985f75bc693954eb66bb788fc2814482bb8bf402f14b72ea2faf5f70cf4ea"
636
+ "sha256": "146cac23328760ae5e71e52b297ea6a7990972d3181b65209f308e0c3b579a1a"
637
637
  },
638
638
  {
639
639
  "path": "runtime/core/hellolynk-neutral-host-store-adapters.mjs",
@@ -693,12 +693,12 @@
693
693
  {
694
694
  "path": "runtime/neutral-host-release-manifest.json",
695
695
  "bytes": 11517,
696
- "sha256": "442496798846e12513029c0b7d2c8e7be32ebff85ee4f90e2163e896a4758ad5"
696
+ "sha256": "ce21197fee88885e91cf7fc3c07cf1ad28690f42efcd48ccfb68314b4002afe1"
697
697
  },
698
698
  {
699
699
  "path": "runtime/neutral-host-release-pin.json",
700
700
  "bytes": 146,
701
- "sha256": "906a18d43a8bd33d4c3f6bebd4286b617255ee26212251b2ef052e5bb2777ff9"
701
+ "sha256": "ce5c6b4f84dd29adbe22bfdce95dafd5b3e3ecdea67ee488a608c173a1b5549c"
702
702
  },
703
703
  {
704
704
  "path": "runtime/platform/windows/configure-agent.ps1",
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "contract": "hellolynk-client-npm-pack-pin-v1",
3
- "manifestSha256": "9570fba93c1a9746b900338df8665f8eae200f3296fa13df8114836b6047ee49"
3
+ "manifestSha256": "6ba432268e44d6416111b4fb5dbfa27c95756f22d11346c6749d784ef7306a84"
4
4
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hellolynk-ai/openclaw-channel",
3
- "version": "0.2.107",
3
+ "version": "0.2.108",
4
4
  "private": true,
5
5
  "description": "HelloLynk Messaging channel plugin for the public OpenClaw Windows client",
6
6
  "type": "module",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hellolynk-ai/openclaw-channel",
3
- "version": "0.2.107",
3
+ "version": "0.2.108",
4
4
  "description": "HelloLynk Messaging for OpenClaw: open conversations and let your AI message other people's AI assistants.",
5
5
  "homepage": "https://hellolynk.com",
6
6
  "repository": {
@@ -387,7 +387,9 @@ export async function issueDeviceRuntimeSession(options) {
387
387
  }
388
388
  return fresh;
389
389
  }
390
- throw new HelloLynkClientError(safeDeviceRuntimeErrorCode(result?.error), {
390
+ const code = response.status === 401 && result?.error === "device_credential_invalid"
391
+ && result?.reason === "device_credential_revoked" ? result.reason : safeDeviceRuntimeErrorCode(result?.error);
392
+ throw new HelloLynkClientError(code, {
391
393
  httpStatus: response.status,
392
394
  retryable: response.status === 408 || response.status === 425 || response.status === 429 || response.status >= 500,
393
395
  });
@@ -584,6 +586,7 @@ export function createDeviceRuntimeSessionManager(options = {}) {
584
586
  );
585
587
  let current = null;
586
588
  let rejectedCredential = null;
589
+ const revokedFingerprints = new Set();
587
590
  let localIssueTail = Promise.resolve();
588
591
 
589
592
  const routeMatches = (session, input) => {
@@ -668,7 +671,15 @@ export function createDeviceRuntimeSessionManager(options = {}) {
668
671
  : null;
669
672
  // The production caller holds the existing session lock, including across
670
673
  // Host processes. An authority denial may drain the current Host.
674
+ const revocationKey = fingerprint && `revoked-${fingerprint}`;
671
675
  if (fingerprint) {
676
+ // An older process may update or clear its temporary rejection for the
677
+ // profile. Keep permanent revocation under the credential's own key.
678
+ if (revokedFingerprints.has(fingerprint)
679
+ || (await credentialRejections?.load(revocationKey).catch(() => null))?.fingerprint === fingerprint) {
680
+ revokedFingerprints.add(fingerprint);
681
+ throw new HelloLynkClientError("device_credential_revoked", { httpStatus: 401 });
682
+ }
672
683
  const isCoolingDown = (rejection) => {
673
684
  if (rejection?.fingerprint !== fingerprint) return false;
674
685
  const age = now() - rejection.rejectedAtMs;
@@ -685,10 +696,14 @@ export function createDeviceRuntimeSessionManager(options = {}) {
685
696
  try {
686
697
  session = reusable(await issue(request), input);
687
698
  } catch (error) {
688
- if (fingerprint && error?.httpStatus === 401 && error.code === "device_credential_invalid") {
689
- rejectedCredential = { fingerprint, rejectedAtMs: now() };
690
- // Preserve the authority denial even if local storage is unavailable.
691
- await credentialRejections?.save(sessionKey, rejectedCredential).catch(() => {});
699
+ if (fingerprint && error?.httpStatus === 401) {
700
+ if (error.code === "device_credential_revoked") {
701
+ revokedFingerprints.add(fingerprint);
702
+ await credentialRejections?.save(revocationKey, { fingerprint, rejectedAtMs: now() }).catch(() => {});
703
+ } else if (error.code === "device_credential_invalid") {
704
+ rejectedCredential = { fingerprint, rejectedAtMs: now() };
705
+ await credentialRejections?.save(sessionKey, rejectedCredential).catch(() => {});
706
+ }
692
707
  }
693
708
  throw error;
694
709
  }
@@ -35,7 +35,7 @@ export const HELLOLYNK_NEUTRAL_HOST_PROCESS_CONTRACT = "hellolynk-neutral-host-p
35
35
  export const HELLOLYNK_NEUTRAL_HOST_DISCOVERY_CONTRACT = "hellolynk-neutral-host-discovery-v1";
36
36
  // Raised with every release batch, together with the six client versions. A Host reports it
37
37
  // in its health; the higher release stays and the lower one makes room.
38
- export const HELLOLYNK_HOST_RELEASE_ORDINAL = 18;
38
+ export const HELLOLYNK_HOST_RELEASE_ORDINAL = 19;
39
39
 
40
40
  const INSTALLATION_LOCK_CONTRACT = "hellolynk-neutral-host-installation-lock-v2";
41
41
  const INSTALLATION_LOCK_MAX_BYTES = 4 * 1024;
@@ -28,7 +28,7 @@
28
28
  },
29
29
  {
30
30
  "path": "core/hellolynk-client-core.mjs",
31
- "sha256": "dbab0f067c1a7f02c43b2696e1f5972288acd4f93a18684bf3cc120edff5cf94"
31
+ "sha256": "1fb8f11e78c0c26e74a4e76dbf295131b63ab6908e964c62e6452e31a694f67a"
32
32
  },
33
33
  {
34
34
  "path": "core/hellolynk-client-profile.mjs",
@@ -192,7 +192,7 @@
192
192
  },
193
193
  {
194
194
  "path": "core/hellolynk-neutral-host-process.mjs",
195
- "sha256": "34b985f75bc693954eb66bb788fc2814482bb8bf402f14b72ea2faf5f70cf4ea"
195
+ "sha256": "146cac23328760ae5e71e52b297ea6a7990972d3181b65209f308e0c3b579a1a"
196
196
  },
197
197
  {
198
198
  "path": "core/hellolynk-neutral-host-store-adapters.mjs",
@@ -1,4 +1,4 @@
1
1
  {
2
2
  "contract": "hellolynk-neutral-host-release-pin-v1",
3
- "manifestSha256": "442496798846e12513029c0b7d2c8e7be32ebff85ee4f90e2163e896a4758ad5"
3
+ "manifestSha256": "ce21197fee88885e91cf7fc3c07cf1ad28690f42efcd48ccfb68314b4002afe1"
4
4
  }