@clawling/clawchat-plugin-openclaw 2026.6.16-3 → 2026.6.16-5

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.
@@ -17,6 +17,26 @@ import { CHANNEL_ID } from "./config.js";
17
17
  export const LEGACY_CHANNEL_ID = "openclaw-clawchat";
18
18
  export const TARGET_CHANNEL_ID = CHANNEL_ID;
19
19
  const BLOCKED_OBJECT_KEYS = new Set(["__proto__", "prototype", "constructor"]);
20
+ /**
21
+ * Channel-config fields that were valid in older plugin versions but have since
22
+ * been removed from the schema (`replyMode` and `stream`, removed 2026-05-27).
23
+ * The channel schema is strict (`additionalProperties: false`), so a config
24
+ * carried over from a pre-removal version makes the host reject the whole
25
+ * channel block and the gateway crash-loops on boot. They must be stripped
26
+ * during migration so an upgrade is seamless.
27
+ */
28
+ const DEPRECATED_CHANNEL_FIELDS = ["replyMode", "stream"];
29
+ /** Remove deprecated fields from a channel block in place; returns those removed. */
30
+ function stripDeprecatedChannelFields(channel) {
31
+ const removed = [];
32
+ for (const field of DEPRECATED_CHANNEL_FIELDS) {
33
+ if (field in channel) {
34
+ delete channel[field];
35
+ removed.push(field);
36
+ }
37
+ }
38
+ return removed;
39
+ }
20
40
  function isBlockedObjectKey(key) {
21
41
  return BLOCKED_OBJECT_KEYS.has(key);
22
42
  }
@@ -75,6 +95,16 @@ export function migrateLegacyClawChatChannelConfig(config) {
75
95
  }
76
96
  delete channels[LEGACY_CHANNEL_ID];
77
97
  }
98
+ // Strip schema-removed fields from the target channel block, whether it
99
+ // was just moved from the legacy key or already present (e.g. a partial
100
+ // migration that previously crashed the gateway on a rejected field).
101
+ const targetChannel = channels[TARGET_CHANNEL_ID];
102
+ if (isRecord(targetChannel)) {
103
+ const removed = stripDeprecatedChannelFields(targetChannel);
104
+ if (removed.length > 0) {
105
+ changes.push(`Stripped deprecated field(s) from channel "${TARGET_CHANNEL_ID}": ${removed.join(", ")}.`);
106
+ }
107
+ }
78
108
  }
79
109
  // plugins.* live under a single `plugins` record.
80
110
  const plugins = next.plugins;
@@ -115,6 +115,10 @@ export async function dispatchOpenclawClawlingInbound(params) {
115
115
  log?.info?.(`[${account.accountId}] clawchat-plugin-openclaw skip: missing sender trace=${envelope.trace_id}`);
116
116
  return;
117
117
  }
118
+ if (sender.id === "system") {
119
+ log?.info?.(`[${account.accountId}] clawchat-plugin-openclaw skip system message msg=${payload.message_id}`);
120
+ return;
121
+ }
118
122
  if (account.userId && sender.id === account.userId) {
119
123
  log?.info?.(`[${account.accountId}] clawchat-plugin-openclaw skip self-echo msg=${payload.message_id} user=${sender.id}`);
120
124
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawling/clawchat-plugin-openclaw",
3
- "version": "2026.6.16-3",
3
+ "version": "2026.6.16-5",
4
4
  "description": "OpenClaw ClawChat channel plugin",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -22,6 +22,30 @@ export const TARGET_CHANNEL_ID = CHANNEL_ID;
22
22
 
23
23
  const BLOCKED_OBJECT_KEYS = new Set(["__proto__", "prototype", "constructor"]);
24
24
 
25
+ /**
26
+ * Channel-config fields that were valid in older plugin versions but have since
27
+ * been removed from the schema (`replyMode` and `stream`, removed 2026-05-27).
28
+ * The channel schema is strict (`additionalProperties: false`), so a config
29
+ * carried over from a pre-removal version makes the host reject the whole
30
+ * channel block and the gateway crash-loops on boot. They must be stripped
31
+ * during migration so an upgrade is seamless.
32
+ */
33
+ const DEPRECATED_CHANNEL_FIELDS = ["replyMode", "stream"] as const;
34
+
35
+ /** Remove deprecated fields from a channel block in place; returns those removed. */
36
+ function stripDeprecatedChannelFields(
37
+ channel: Record<string, unknown>,
38
+ ): string[] {
39
+ const removed: string[] = [];
40
+ for (const field of DEPRECATED_CHANNEL_FIELDS) {
41
+ if (field in channel) {
42
+ delete channel[field];
43
+ removed.push(field);
44
+ }
45
+ }
46
+ return removed;
47
+ }
48
+
25
49
  function isBlockedObjectKey(key: string): boolean {
26
50
  return BLOCKED_OBJECT_KEYS.has(key);
27
51
  }
@@ -92,6 +116,19 @@ export function migrateLegacyClawChatChannelConfig(config: OpenClawConfig): {
92
116
  }
93
117
  delete channels[LEGACY_CHANNEL_ID];
94
118
  }
119
+
120
+ // Strip schema-removed fields from the target channel block, whether it
121
+ // was just moved from the legacy key or already present (e.g. a partial
122
+ // migration that previously crashed the gateway on a rejected field).
123
+ const targetChannel = channels[TARGET_CHANNEL_ID];
124
+ if (isRecord(targetChannel)) {
125
+ const removed = stripDeprecatedChannelFields(targetChannel);
126
+ if (removed.length > 0) {
127
+ changes.push(
128
+ `Stripped deprecated field(s) from channel "${TARGET_CHANNEL_ID}": ${removed.join(", ")}.`,
129
+ );
130
+ }
131
+ }
95
132
  }
96
133
 
97
134
  // plugins.* live under a single `plugins` record.
package/src/inbound.ts CHANGED
@@ -222,6 +222,12 @@ export async function dispatchOpenclawClawlingInbound(
222
222
  );
223
223
  return;
224
224
  }
225
+ if (sender.id === "system") {
226
+ log?.info?.(
227
+ `[${account.accountId}] clawchat-plugin-openclaw skip system message msg=${payload.message_id}`,
228
+ );
229
+ return;
230
+ }
225
231
  if (account.userId && sender.id === account.userId) {
226
232
  log?.info?.(
227
233
  `[${account.accountId}] clawchat-plugin-openclaw skip self-echo msg=${payload.message_id} user=${sender.id}`,