@clawling/clawchat-plugin-openclaw 2026.6.16-2 → 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.
- package/dist/src/config-compat.js +30 -0
- package/dist/src/plugin-report.js +30 -3
- package/package.json +1 -1
- package/src/config-compat.ts +37 -0
- package/src/plugin-report.ts +31 -3
|
@@ -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;
|
|
@@ -1,11 +1,38 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
2
4
|
import { createOpenclawClawlingApiClient } from "./api-client.js";
|
|
3
|
-
|
|
5
|
+
const PACKAGE_NAME = "@clawling/clawchat-plugin-openclaw";
|
|
6
|
+
/**
|
|
7
|
+
* Best-effort read of this plugin's package version; "unknown" on failure.
|
|
8
|
+
*
|
|
9
|
+
* Walks up from this module's directory to the nearest package.json whose
|
|
10
|
+
* name matches this plugin, instead of assuming a fixed relative depth. The
|
|
11
|
+
* compiled module lives at dist/src/plugin-report.js (rootDir "." + outDir
|
|
12
|
+
* "dist"), so a hard-coded "../package.json" resolves to the non-existent
|
|
13
|
+
* dist/package.json at runtime and always falls back to "unknown" — even
|
|
14
|
+
* though it happens to work when tests run straight from src/.
|
|
15
|
+
*/
|
|
4
16
|
export function resolvePluginVersion() {
|
|
5
17
|
try {
|
|
6
18
|
const require = createRequire(import.meta.url);
|
|
7
|
-
|
|
8
|
-
|
|
19
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
20
|
+
// Bounded climb (handles dist/src, src, and any reasonable nesting).
|
|
21
|
+
for (let i = 0; i < 8; i += 1) {
|
|
22
|
+
try {
|
|
23
|
+
const pkg = require(join(dir, "package.json"));
|
|
24
|
+
if (pkg.name === PACKAGE_NAME && pkg.version)
|
|
25
|
+
return pkg.version;
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// no package.json at this level — keep climbing
|
|
29
|
+
}
|
|
30
|
+
const parent = dirname(dir);
|
|
31
|
+
if (parent === dir)
|
|
32
|
+
break;
|
|
33
|
+
dir = parent;
|
|
34
|
+
}
|
|
35
|
+
return "unknown";
|
|
9
36
|
}
|
|
10
37
|
catch {
|
|
11
38
|
return "unknown";
|
package/package.json
CHANGED
package/src/config-compat.ts
CHANGED
|
@@ -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/plugin-report.ts
CHANGED
|
@@ -1,12 +1,40 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
import { fileURLToPath } from "node:url";
|
|
2
4
|
import { createOpenclawClawlingApiClient } from "./api-client.ts";
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
const PACKAGE_NAME = "@clawling/clawchat-plugin-openclaw";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Best-effort read of this plugin's package version; "unknown" on failure.
|
|
10
|
+
*
|
|
11
|
+
* Walks up from this module's directory to the nearest package.json whose
|
|
12
|
+
* name matches this plugin, instead of assuming a fixed relative depth. The
|
|
13
|
+
* compiled module lives at dist/src/plugin-report.js (rootDir "." + outDir
|
|
14
|
+
* "dist"), so a hard-coded "../package.json" resolves to the non-existent
|
|
15
|
+
* dist/package.json at runtime and always falls back to "unknown" — even
|
|
16
|
+
* though it happens to work when tests run straight from src/.
|
|
17
|
+
*/
|
|
5
18
|
export function resolvePluginVersion(): string {
|
|
6
19
|
try {
|
|
7
20
|
const require = createRequire(import.meta.url);
|
|
8
|
-
|
|
9
|
-
|
|
21
|
+
let dir = dirname(fileURLToPath(import.meta.url));
|
|
22
|
+
// Bounded climb (handles dist/src, src, and any reasonable nesting).
|
|
23
|
+
for (let i = 0; i < 8; i += 1) {
|
|
24
|
+
try {
|
|
25
|
+
const pkg = require(join(dir, "package.json")) as {
|
|
26
|
+
name?: string;
|
|
27
|
+
version?: string;
|
|
28
|
+
};
|
|
29
|
+
if (pkg.name === PACKAGE_NAME && pkg.version) return pkg.version;
|
|
30
|
+
} catch {
|
|
31
|
+
// no package.json at this level — keep climbing
|
|
32
|
+
}
|
|
33
|
+
const parent = dirname(dir);
|
|
34
|
+
if (parent === dir) break;
|
|
35
|
+
dir = parent;
|
|
36
|
+
}
|
|
37
|
+
return "unknown";
|
|
10
38
|
} catch {
|
|
11
39
|
return "unknown";
|
|
12
40
|
}
|