@clawling/clawchat-plugin-openclaw 2026.8.5-1 → 2026.8.6-1
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/dist/src/inbound.js +7 -2
- package/dist/src/protocol-types.js +8 -0
- package/dist/src/runtime.js +34 -14
- package/package.json +1 -1
- package/src/inbound.ts +7 -1
- package/src/protocol-types.ts +9 -0
- package/src/runtime.ts +37 -16
package/dist/src/inbound.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EVENT, } from "./protocol-types.js";
|
|
1
|
+
import { EVENT, MENTION_ALL_USER_ID, } from "./protocol-types.js";
|
|
2
2
|
import { extractMediaFragments, fragmentsToText } from "./message-mapper.js";
|
|
3
3
|
import { hasRenderableText, isInboundMessagePayload } from "./protocol.js";
|
|
4
4
|
function normalizeSender(sender) {
|
|
@@ -73,11 +73,16 @@ function mentionedUserIds(mentions) {
|
|
|
73
73
|
/**
|
|
74
74
|
* Exported for direct unit testing. Direct chats always count as addressed;
|
|
75
75
|
* group chats require a mention unless config opts into all group messages.
|
|
76
|
+
*
|
|
77
|
+
* `MENTION_ALL_USER_ID` ("all") is the `@everyone` sentinel — it addresses
|
|
78
|
+
* every member of the room, this agent included, so it counts as a mention
|
|
79
|
+
* even though it never equals our own user id.
|
|
76
80
|
*/
|
|
77
81
|
export function detectMention(params) {
|
|
78
82
|
if (params.chatType === "direct")
|
|
79
83
|
return true;
|
|
80
|
-
|
|
84
|
+
const ids = mentionedUserIds(normalizeMentionUsers(params.mentions));
|
|
85
|
+
return ids.includes(params.userId) || ids.includes(MENTION_ALL_USER_ID);
|
|
81
86
|
}
|
|
82
87
|
export async function dispatchOpenclawClawlingInbound(params) {
|
|
83
88
|
const { envelope, account, log } = params;
|
|
@@ -22,6 +22,14 @@ export const EVENT = {
|
|
|
22
22
|
PING: "ping",
|
|
23
23
|
PONG: "pong",
|
|
24
24
|
};
|
|
25
|
+
/**
|
|
26
|
+
* The `user_id` an `@everyone` mention carries on the wire — a reserved
|
|
27
|
+
* sentinel, not a real user id. The server never expands it into one mention
|
|
28
|
+
* per member, so every reader must decide for itself that it includes them.
|
|
29
|
+
* It can appear both as a `mention` fragment and as a `context.mentions`
|
|
30
|
+
* element. See `docs/client-integration.md` §10.2.
|
|
31
|
+
*/
|
|
32
|
+
export const MENTION_ALL_USER_ID = "all";
|
|
25
33
|
export class AuthError extends Error {
|
|
26
34
|
name = "AuthError";
|
|
27
35
|
}
|
package/dist/src/runtime.js
CHANGED
|
@@ -2803,6 +2803,37 @@ export async function startOpenclawClawlingGateway(params) {
|
|
|
2803
2803
|
conversationId: claimedBootstrap.conversationId,
|
|
2804
2804
|
}));
|
|
2805
2805
|
};
|
|
2806
|
+
const markBootstrapSent = (reason) => {
|
|
2807
|
+
if (!bootstrap)
|
|
2808
|
+
return;
|
|
2809
|
+
const claimedBootstrap = bootstrap;
|
|
2810
|
+
const marked = recordConnection("activation bootstrap sent", () => store.markActivationBootstrapSent?.({
|
|
2811
|
+
platform: "openclaw",
|
|
2812
|
+
accountId,
|
|
2813
|
+
conversationId: claimedBootstrap.conversationId,
|
|
2814
|
+
}));
|
|
2815
|
+
if (marked !== true) {
|
|
2816
|
+
// The UPDATE is guarded on bootstrap_sent = 0 AND bootstrap_claimed_at
|
|
2817
|
+
// IS NOT NULL, so a stale re-claim makes this a no-op — and the row
|
|
2818
|
+
// then stays re-greetable on every later reconnect. Never swallow it.
|
|
2819
|
+
log?.error?.(`[${accountId}] clawchat-plugin-openclaw activation bootstrap not marked sent (${reason}); the greeting may repeat on reconnect`);
|
|
2820
|
+
}
|
|
2821
|
+
// Delivered — stop any pending retry.
|
|
2822
|
+
clearBootstrapRetry();
|
|
2823
|
+
};
|
|
2824
|
+
// Single decision point for every exit after the claim. The greeting is
|
|
2825
|
+
// emitted *inside* the dispatched turn, so once it has reached the user the
|
|
2826
|
+
// claim must never be rolled back: releasing it lets the next connection
|
|
2827
|
+
// claim again and greet a second time. Only a turn that delivered nothing
|
|
2828
|
+
// is safe to retry.
|
|
2829
|
+
const settleBootstrap = (reason) => {
|
|
2830
|
+
if (bootstrapGreetingDelivered) {
|
|
2831
|
+
markBootstrapSent(reason);
|
|
2832
|
+
return;
|
|
2833
|
+
}
|
|
2834
|
+
releaseBootstrap();
|
|
2835
|
+
armBootstrapRetry();
|
|
2836
|
+
};
|
|
2806
2837
|
try {
|
|
2807
2838
|
bootstrap = recordConnection("activation bootstrap claim", () => store.claimPendingActivationBootstrap?.({ platform: "openclaw", accountId }));
|
|
2808
2839
|
if (!bootstrap) {
|
|
@@ -2819,8 +2850,7 @@ export async function startOpenclawClawlingGateway(params) {
|
|
|
2819
2850
|
bootstrapGreetingDelivered = false;
|
|
2820
2851
|
const result = await handleInboundEnvelope(buildActivationBootstrapEnvelope({ account, conversationId: claimedBootstrap.conversationId }));
|
|
2821
2852
|
if (result !== "submitted") {
|
|
2822
|
-
|
|
2823
|
-
armBootstrapRetry();
|
|
2853
|
+
settleBootstrap("turn was not submitted");
|
|
2824
2854
|
return;
|
|
2825
2855
|
}
|
|
2826
2856
|
// Only mark the bootstrap done once the greeting was actually delivered
|
|
@@ -2831,21 +2861,11 @@ export async function startOpenclawClawlingGateway(params) {
|
|
|
2831
2861
|
// rather than silently consuming it forever or waiting for the next reconnect.
|
|
2832
2862
|
if (!bootstrapGreetingDelivered) {
|
|
2833
2863
|
log?.info?.(`[${accountId}] clawchat-plugin-openclaw activation bootstrap dispatched but greeting was not delivered; leaving pending for retry`);
|
|
2834
|
-
releaseBootstrap();
|
|
2835
|
-
armBootstrapRetry();
|
|
2836
|
-
return;
|
|
2837
2864
|
}
|
|
2838
|
-
|
|
2839
|
-
platform: "openclaw",
|
|
2840
|
-
accountId,
|
|
2841
|
-
conversationId: claimedBootstrap.conversationId,
|
|
2842
|
-
}));
|
|
2843
|
-
// Delivered — stop any pending retry.
|
|
2844
|
-
clearBootstrapRetry();
|
|
2865
|
+
settleBootstrap("turn submitted");
|
|
2845
2866
|
}
|
|
2846
2867
|
catch (err) {
|
|
2847
|
-
|
|
2848
|
-
armBootstrapRetry();
|
|
2868
|
+
settleBootstrap("dispatch threw");
|
|
2849
2869
|
log?.error?.(`[${accountId}] clawchat-plugin-openclaw activation bootstrap failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
2850
2870
|
}
|
|
2851
2871
|
finally {
|
package/package.json
CHANGED
package/src/inbound.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
EVENT,
|
|
3
|
+
MENTION_ALL_USER_ID,
|
|
3
4
|
type ChatType,
|
|
4
5
|
type Envelope,
|
|
5
6
|
} from "./protocol-types.ts";
|
|
@@ -180,6 +181,10 @@ function mentionedUserIds(mentions: MentionedUser[]): string[] {
|
|
|
180
181
|
/**
|
|
181
182
|
* Exported for direct unit testing. Direct chats always count as addressed;
|
|
182
183
|
* group chats require a mention unless config opts into all group messages.
|
|
184
|
+
*
|
|
185
|
+
* `MENTION_ALL_USER_ID` ("all") is the `@everyone` sentinel — it addresses
|
|
186
|
+
* every member of the room, this agent included, so it counts as a mention
|
|
187
|
+
* even though it never equals our own user id.
|
|
183
188
|
*/
|
|
184
189
|
export function detectMention(params: {
|
|
185
190
|
mentions: unknown[];
|
|
@@ -187,7 +192,8 @@ export function detectMention(params: {
|
|
|
187
192
|
userId: string;
|
|
188
193
|
}): boolean {
|
|
189
194
|
if (params.chatType === "direct") return true;
|
|
190
|
-
|
|
195
|
+
const ids = mentionedUserIds(normalizeMentionUsers(params.mentions));
|
|
196
|
+
return ids.includes(params.userId) || ids.includes(MENTION_ALL_USER_ID);
|
|
191
197
|
}
|
|
192
198
|
|
|
193
199
|
export async function dispatchOpenclawClawlingInbound(
|
package/src/protocol-types.ts
CHANGED
|
@@ -23,6 +23,15 @@ export const EVENT = {
|
|
|
23
23
|
PONG: "pong",
|
|
24
24
|
} as const;
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
* The `user_id` an `@everyone` mention carries on the wire — a reserved
|
|
28
|
+
* sentinel, not a real user id. The server never expands it into one mention
|
|
29
|
+
* per member, so every reader must decide for itself that it includes them.
|
|
30
|
+
* It can appear both as a `mention` fragment and as a `context.mentions`
|
|
31
|
+
* element. See `docs/client-integration.md` §10.2.
|
|
32
|
+
*/
|
|
33
|
+
export const MENTION_ALL_USER_ID = "all";
|
|
34
|
+
|
|
26
35
|
export type KnownEventName = typeof EVENT[keyof typeof EVENT];
|
|
27
36
|
export type EventName = KnownEventName | string;
|
|
28
37
|
export type ChatType = "direct" | "group";
|
package/src/runtime.ts
CHANGED
|
@@ -3333,6 +3333,40 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
3333
3333
|
}),
|
|
3334
3334
|
);
|
|
3335
3335
|
};
|
|
3336
|
+
const markBootstrapSent = (reason: string) => {
|
|
3337
|
+
if (!bootstrap) return;
|
|
3338
|
+
const claimedBootstrap = bootstrap;
|
|
3339
|
+
const marked = recordConnection("activation bootstrap sent", () =>
|
|
3340
|
+
store.markActivationBootstrapSent?.({
|
|
3341
|
+
platform: "openclaw",
|
|
3342
|
+
accountId,
|
|
3343
|
+
conversationId: claimedBootstrap.conversationId,
|
|
3344
|
+
}),
|
|
3345
|
+
);
|
|
3346
|
+
if (marked !== true) {
|
|
3347
|
+
// The UPDATE is guarded on bootstrap_sent = 0 AND bootstrap_claimed_at
|
|
3348
|
+
// IS NOT NULL, so a stale re-claim makes this a no-op — and the row
|
|
3349
|
+
// then stays re-greetable on every later reconnect. Never swallow it.
|
|
3350
|
+
log?.error?.(
|
|
3351
|
+
`[${accountId}] clawchat-plugin-openclaw activation bootstrap not marked sent (${reason}); the greeting may repeat on reconnect`,
|
|
3352
|
+
);
|
|
3353
|
+
}
|
|
3354
|
+
// Delivered — stop any pending retry.
|
|
3355
|
+
clearBootstrapRetry();
|
|
3356
|
+
};
|
|
3357
|
+
// Single decision point for every exit after the claim. The greeting is
|
|
3358
|
+
// emitted *inside* the dispatched turn, so once it has reached the user the
|
|
3359
|
+
// claim must never be rolled back: releasing it lets the next connection
|
|
3360
|
+
// claim again and greet a second time. Only a turn that delivered nothing
|
|
3361
|
+
// is safe to retry.
|
|
3362
|
+
const settleBootstrap = (reason: string) => {
|
|
3363
|
+
if (bootstrapGreetingDelivered) {
|
|
3364
|
+
markBootstrapSent(reason);
|
|
3365
|
+
return;
|
|
3366
|
+
}
|
|
3367
|
+
releaseBootstrap();
|
|
3368
|
+
armBootstrapRetry();
|
|
3369
|
+
};
|
|
3336
3370
|
try {
|
|
3337
3371
|
bootstrap = recordConnection("activation bootstrap claim", () =>
|
|
3338
3372
|
store.claimPendingActivationBootstrap?.({ platform: "openclaw", accountId }),
|
|
@@ -3352,8 +3386,7 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
3352
3386
|
buildActivationBootstrapEnvelope({ account, conversationId: claimedBootstrap.conversationId }),
|
|
3353
3387
|
);
|
|
3354
3388
|
if (result !== "submitted") {
|
|
3355
|
-
|
|
3356
|
-
armBootstrapRetry();
|
|
3389
|
+
settleBootstrap("turn was not submitted");
|
|
3357
3390
|
return;
|
|
3358
3391
|
}
|
|
3359
3392
|
// Only mark the bootstrap done once the greeting was actually delivered
|
|
@@ -3366,22 +3399,10 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
3366
3399
|
log?.info?.(
|
|
3367
3400
|
`[${accountId}] clawchat-plugin-openclaw activation bootstrap dispatched but greeting was not delivered; leaving pending for retry`,
|
|
3368
3401
|
);
|
|
3369
|
-
releaseBootstrap();
|
|
3370
|
-
armBootstrapRetry();
|
|
3371
|
-
return;
|
|
3372
3402
|
}
|
|
3373
|
-
|
|
3374
|
-
store.markActivationBootstrapSent?.({
|
|
3375
|
-
platform: "openclaw",
|
|
3376
|
-
accountId,
|
|
3377
|
-
conversationId: claimedBootstrap.conversationId,
|
|
3378
|
-
}),
|
|
3379
|
-
);
|
|
3380
|
-
// Delivered — stop any pending retry.
|
|
3381
|
-
clearBootstrapRetry();
|
|
3403
|
+
settleBootstrap("turn submitted");
|
|
3382
3404
|
} catch (err) {
|
|
3383
|
-
|
|
3384
|
-
armBootstrapRetry();
|
|
3405
|
+
settleBootstrap("dispatch threw");
|
|
3385
3406
|
log?.error?.(
|
|
3386
3407
|
`[${accountId}] clawchat-plugin-openclaw activation bootstrap failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
3387
3408
|
);
|