@clawling/clawchat-plugin-openclaw 2026.6.30-1 → 2026.6.30-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/dist/src/runtime.js +32 -5
- package/package.json +1 -1
- package/src/runtime.ts +34 -5
package/dist/src/runtime.js
CHANGED
|
@@ -279,12 +279,17 @@ function withClawChatSessionScope(cfg) {
|
|
|
279
279
|
};
|
|
280
280
|
}
|
|
281
281
|
function buildActivationBootstrapText() {
|
|
282
|
+
// Worded to make the greeting the single required action. Earlier wording
|
|
283
|
+
// ("ClawChat activation bootstrap: ... do both ...") led some agents to treat
|
|
284
|
+
// it as a setup task and write a `BOOTSTRAP.md` file instead of replying, so
|
|
285
|
+
// no greeting reached the user. Lead with the chat reply, forbid file/tool
|
|
286
|
+
// detours, and keep the profile update strictly optional and secondary.
|
|
282
287
|
return [
|
|
283
|
-
"
|
|
284
|
-
"
|
|
285
|
-
"
|
|
286
|
-
"
|
|
287
|
-
"Do not ask the user for profile information
|
|
288
|
+
"You are now connected to a ClawChat direct conversation with your user.",
|
|
289
|
+
"Reply now with one short, friendly greeting message in this conversation: introduce yourself and say you are connected and ready.",
|
|
290
|
+
"Send it as a normal chat reply. Do not write or create any files or notes, and do not call tools just to greet.",
|
|
291
|
+
"Only if you already have your own profile details (display name, bio, or avatar) may you also call `clawchat_update_account_profile` (use `clawchat_upload_avatar_image` first for a local avatar image); otherwise skip that and just greet.",
|
|
292
|
+
"Do not ask the user for profile information.",
|
|
288
293
|
].join("\n");
|
|
289
294
|
}
|
|
290
295
|
function buildActivationBootstrapEnvelope(params) {
|
|
@@ -1440,6 +1445,11 @@ export async function startOpenclawClawlingGateway(params) {
|
|
|
1440
1445
|
}));
|
|
1441
1446
|
};
|
|
1442
1447
|
let dispatchActivationBootstrap = async () => { };
|
|
1448
|
+
// Set by dispatchTurnToAgent when it dispatches the synthetic
|
|
1449
|
+
// `clawchat-bootstrap` turn: true only if the agent actually produced a final
|
|
1450
|
+
// outbound message (the greeting). The bootstrap dispatcher reads it to decide
|
|
1451
|
+
// whether to mark the bootstrap sent or leave it pending for a later retry.
|
|
1452
|
+
let bootstrapProducedFinal = false;
|
|
1443
1453
|
client.on("state", ({ from, to }) => {
|
|
1444
1454
|
log?.info?.(`[${accountId}] clawchat-plugin-openclaw state ${from} -> ${to}`);
|
|
1445
1455
|
wsReady = to === "connected";
|
|
@@ -2131,6 +2141,12 @@ export async function startOpenclawClawlingGateway(params) {
|
|
|
2131
2141
|
});
|
|
2132
2142
|
const counts = dispatchResult?.counts ?? {};
|
|
2133
2143
|
const queuedFinal = Boolean(dispatchResult?.queuedFinal);
|
|
2144
|
+
if (turn.senderId === "clawchat-bootstrap") {
|
|
2145
|
+
// Did the agent actually emit a greeting? A final outbound message
|
|
2146
|
+
// means yes; block/tool-only (or nothing) means the greeting never
|
|
2147
|
+
// reached the user, so the bootstrap dispatcher will keep it pending.
|
|
2148
|
+
bootstrapProducedFinal = queuedFinal || (counts.final ?? 0) > 0;
|
|
2149
|
+
}
|
|
2134
2150
|
log?.info?.(`[${accountId}] clawchat-plugin-openclaw dispatch complete msg=${turn.messageId} queuedFinal=${queuedFinal} counts=${JSON.stringify(counts)}`);
|
|
2135
2151
|
if (!queuedFinal && Object.values(counts).every((n) => !n)) {
|
|
2136
2152
|
log?.info?.(`[${accountId}] clawchat-plugin-openclaw NO reply was produced (no final / block / tool dispatched). ` +
|
|
@@ -2388,11 +2404,22 @@ export async function startOpenclawClawlingGateway(params) {
|
|
|
2388
2404
|
if (!bootstrap)
|
|
2389
2405
|
return;
|
|
2390
2406
|
const claimedBootstrap = bootstrap;
|
|
2407
|
+
bootstrapProducedFinal = false;
|
|
2391
2408
|
const result = await handleInboundEnvelope(buildActivationBootstrapEnvelope({ account, conversationId: claimedBootstrap.conversationId }));
|
|
2392
2409
|
if (result !== "submitted") {
|
|
2393
2410
|
releaseBootstrap();
|
|
2394
2411
|
return;
|
|
2395
2412
|
}
|
|
2413
|
+
// Only mark the bootstrap done once the agent has actually sent a greeting
|
|
2414
|
+
// (a final outbound message). If the turn was handed off but produced no
|
|
2415
|
+
// final reply — e.g. the agent went off to write a file/note instead of
|
|
2416
|
+
// replying — leave the bootstrap pending (release the claim) so the next
|
|
2417
|
+
// ready re-dispatches it, rather than silently consuming it forever.
|
|
2418
|
+
if (!bootstrapProducedFinal) {
|
|
2419
|
+
log?.info?.(`[${accountId}] clawchat-plugin-openclaw activation bootstrap dispatched but produced no final reply; leaving pending for retry`);
|
|
2420
|
+
releaseBootstrap();
|
|
2421
|
+
return;
|
|
2422
|
+
}
|
|
2396
2423
|
recordConnection("activation bootstrap sent", () => store.markActivationBootstrapSent?.({
|
|
2397
2424
|
platform: "openclaw",
|
|
2398
2425
|
accountId,
|
package/package.json
CHANGED
package/src/runtime.ts
CHANGED
|
@@ -427,12 +427,17 @@ function withClawChatSessionScope(cfg: OpenClawConfig): OpenClawConfig {
|
|
|
427
427
|
}
|
|
428
428
|
|
|
429
429
|
function buildActivationBootstrapText(): string {
|
|
430
|
+
// Worded to make the greeting the single required action. Earlier wording
|
|
431
|
+
// ("ClawChat activation bootstrap: ... do both ...") led some agents to treat
|
|
432
|
+
// it as a setup task and write a `BOOTSTRAP.md` file instead of replying, so
|
|
433
|
+
// no greeting reached the user. Lead with the chat reply, forbid file/tool
|
|
434
|
+
// detours, and keep the profile update strictly optional and secondary.
|
|
430
435
|
return [
|
|
431
|
-
"
|
|
432
|
-
"
|
|
433
|
-
"
|
|
434
|
-
"
|
|
435
|
-
"Do not ask the user for profile information
|
|
436
|
+
"You are now connected to a ClawChat direct conversation with your user.",
|
|
437
|
+
"Reply now with one short, friendly greeting message in this conversation: introduce yourself and say you are connected and ready.",
|
|
438
|
+
"Send it as a normal chat reply. Do not write or create any files or notes, and do not call tools just to greet.",
|
|
439
|
+
"Only if you already have your own profile details (display name, bio, or avatar) may you also call `clawchat_update_account_profile` (use `clawchat_upload_avatar_image` first for a local avatar image); otherwise skip that and just greet.",
|
|
440
|
+
"Do not ask the user for profile information.",
|
|
436
441
|
].join("\n");
|
|
437
442
|
}
|
|
438
443
|
|
|
@@ -1816,6 +1821,11 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
1816
1821
|
);
|
|
1817
1822
|
};
|
|
1818
1823
|
let dispatchActivationBootstrap: () => Promise<void> = async () => {};
|
|
1824
|
+
// Set by dispatchTurnToAgent when it dispatches the synthetic
|
|
1825
|
+
// `clawchat-bootstrap` turn: true only if the agent actually produced a final
|
|
1826
|
+
// outbound message (the greeting). The bootstrap dispatcher reads it to decide
|
|
1827
|
+
// whether to mark the bootstrap sent or leave it pending for a later retry.
|
|
1828
|
+
let bootstrapProducedFinal = false;
|
|
1819
1829
|
|
|
1820
1830
|
client.on("state", ({ from, to }) => {
|
|
1821
1831
|
log?.info?.(`[${accountId}] clawchat-plugin-openclaw state ${from} -> ${to}`);
|
|
@@ -2579,6 +2589,12 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
2579
2589
|
const queuedFinal = Boolean(
|
|
2580
2590
|
(dispatchResult as { queuedFinal?: boolean } | undefined)?.queuedFinal,
|
|
2581
2591
|
);
|
|
2592
|
+
if (turn.senderId === "clawchat-bootstrap") {
|
|
2593
|
+
// Did the agent actually emit a greeting? A final outbound message
|
|
2594
|
+
// means yes; block/tool-only (or nothing) means the greeting never
|
|
2595
|
+
// reached the user, so the bootstrap dispatcher will keep it pending.
|
|
2596
|
+
bootstrapProducedFinal = queuedFinal || (counts.final ?? 0) > 0;
|
|
2597
|
+
}
|
|
2582
2598
|
log?.info?.(
|
|
2583
2599
|
`[${accountId}] clawchat-plugin-openclaw dispatch complete msg=${turn.messageId} queuedFinal=${queuedFinal} counts=${JSON.stringify(counts)}`,
|
|
2584
2600
|
);
|
|
@@ -2877,6 +2893,7 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
2877
2893
|
);
|
|
2878
2894
|
if (!bootstrap) return;
|
|
2879
2895
|
const claimedBootstrap = bootstrap;
|
|
2896
|
+
bootstrapProducedFinal = false;
|
|
2880
2897
|
const result = await handleInboundEnvelope(
|
|
2881
2898
|
buildActivationBootstrapEnvelope({ account, conversationId: claimedBootstrap.conversationId }),
|
|
2882
2899
|
);
|
|
@@ -2884,6 +2901,18 @@ export async function startOpenclawClawlingGateway(params: StartGatewayParams):
|
|
|
2884
2901
|
releaseBootstrap();
|
|
2885
2902
|
return;
|
|
2886
2903
|
}
|
|
2904
|
+
// Only mark the bootstrap done once the agent has actually sent a greeting
|
|
2905
|
+
// (a final outbound message). If the turn was handed off but produced no
|
|
2906
|
+
// final reply — e.g. the agent went off to write a file/note instead of
|
|
2907
|
+
// replying — leave the bootstrap pending (release the claim) so the next
|
|
2908
|
+
// ready re-dispatches it, rather than silently consuming it forever.
|
|
2909
|
+
if (!bootstrapProducedFinal) {
|
|
2910
|
+
log?.info?.(
|
|
2911
|
+
`[${accountId}] clawchat-plugin-openclaw activation bootstrap dispatched but produced no final reply; leaving pending for retry`,
|
|
2912
|
+
);
|
|
2913
|
+
releaseBootstrap();
|
|
2914
|
+
return;
|
|
2915
|
+
}
|
|
2887
2916
|
recordConnection("activation bootstrap sent", () =>
|
|
2888
2917
|
store.markActivationBootstrapSent?.({
|
|
2889
2918
|
platform: "openclaw",
|