@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.
- package/clients/core/hellolynk-client-core.mjs +20 -5
- package/clients/core/hellolynk-neutral-host-process.mjs +1 -1
- package/hellolynk-client-pack-manifest.json +11 -11
- package/hellolynk-client-pack-pin.json +1 -1
- package/integrations/openclaw-channel/package.json +1 -1
- package/package.json +1 -1
- package/runtime/core/hellolynk-client-core.mjs +20 -5
- package/runtime/core/hellolynk-neutral-host-process.mjs +1 -1
- package/runtime/neutral-host-release-manifest.json +2 -2
- package/runtime/neutral-host-release-pin.json +1 -1
|
@@ -387,7 +387,9 @@ export async function issueDeviceRuntimeSession(options) {
|
|
|
387
387
|
}
|
|
388
388
|
return fresh;
|
|
389
389
|
}
|
|
390
|
-
|
|
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
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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 =
|
|
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.
|
|
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":
|
|
36
|
-
"sha256": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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":
|
|
436
|
-
"sha256": "
|
|
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": "
|
|
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": "
|
|
696
|
+
"sha256": "ce21197fee88885e91cf7fc3c07cf1ad28690f42efcd48ccfb68314b4002afe1"
|
|
697
697
|
},
|
|
698
698
|
{
|
|
699
699
|
"path": "runtime/neutral-host-release-pin.json",
|
|
700
700
|
"bytes": 146,
|
|
701
|
-
"sha256": "
|
|
701
|
+
"sha256": "ce5c6b4f84dd29adbe22bfdce95dafd5b3e3ecdea67ee488a608c173a1b5549c"
|
|
702
702
|
},
|
|
703
703
|
{
|
|
704
704
|
"path": "runtime/platform/windows/configure-agent.ps1",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hellolynk-ai/openclaw-channel",
|
|
3
|
-
"version": "0.2.
|
|
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
|
-
|
|
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
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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 =
|
|
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": "
|
|
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": "
|
|
195
|
+
"sha256": "146cac23328760ae5e71e52b297ea6a7990972d3181b65209f308e0c3b579a1a"
|
|
196
196
|
},
|
|
197
197
|
{
|
|
198
198
|
"path": "core/hellolynk-neutral-host-store-adapters.mjs",
|