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

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;
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-4",
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.