@clawling/clawchat-plugin-openclaw 2026.5.12-28
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/INSTALL.md +64 -0
- package/README.md +227 -0
- package/dist/index.js +20 -0
- package/dist/setup-entry.js +3 -0
- package/dist/src/api-client.js +263 -0
- package/dist/src/api-types.js +17 -0
- package/dist/src/api-types.test-d.js +10 -0
- package/dist/src/buffered-stream.js +177 -0
- package/dist/src/channel.js +66 -0
- package/dist/src/channel.setup.js +119 -0
- package/dist/src/clawchat-memory.js +403 -0
- package/dist/src/clawchat-metadata.js +310 -0
- package/dist/src/client.js +35 -0
- package/dist/src/commands.js +35 -0
- package/dist/src/config.js +274 -0
- package/dist/src/group-message-coalescer.js +119 -0
- package/dist/src/inbound.js +170 -0
- package/dist/src/llm-context-debug.js +86 -0
- package/dist/src/login.runtime.js +204 -0
- package/dist/src/media-runtime.js +85 -0
- package/dist/src/message-mapper.js +146 -0
- package/dist/src/mock-transport.js +31 -0
- package/dist/src/outbound.js +628 -0
- package/dist/src/plugin-prompts.js +89 -0
- package/dist/src/profile-prompt.js +269 -0
- package/dist/src/profile-sync.js +110 -0
- package/dist/src/prompt-injection.js +25 -0
- package/dist/src/protocol-types.js +63 -0
- package/dist/src/protocol-types.typecheck.js +1 -0
- package/dist/src/protocol.js +33 -0
- package/dist/src/reply-dispatcher.js +422 -0
- package/dist/src/runtime.js +1254 -0
- package/dist/src/storage.js +525 -0
- package/dist/src/streaming.js +65 -0
- package/dist/src/terminal-send.js +36 -0
- package/dist/src/tools-schema.js +208 -0
- package/dist/src/tools.js +920 -0
- package/dist/src/ws-alignment.js +178 -0
- package/dist/src/ws-client.js +588 -0
- package/dist/src/ws-log.js +19 -0
- package/index.ts +24 -0
- package/openclaw.plugin.json +169 -0
- package/package.json +80 -0
- package/prompts/default-group-bio.md +19 -0
- package/prompts/default-owner-behavior.md +27 -0
- package/prompts/platform.md +13 -0
- package/setup-entry.ts +4 -0
- package/skills/clawchat/SKILL.md +91 -0
- package/src/api-client.test.ts +827 -0
- package/src/api-client.ts +414 -0
- package/src/api-types.ts +146 -0
- package/src/channel.outbound.test.ts +433 -0
- package/src/channel.setup.ts +145 -0
- package/src/channel.test.ts +262 -0
- package/src/channel.ts +81 -0
- package/src/clawchat-memory.test.ts +480 -0
- package/src/clawchat-memory.ts +533 -0
- package/src/clawchat-metadata.test.ts +477 -0
- package/src/clawchat-metadata.ts +429 -0
- package/src/client.test.ts +169 -0
- package/src/client.ts +56 -0
- package/src/commands.test.ts +39 -0
- package/src/commands.ts +41 -0
- package/src/config.test.ts +344 -0
- package/src/config.ts +404 -0
- package/src/group-message-coalescer.test.ts +237 -0
- package/src/group-message-coalescer.ts +171 -0
- package/src/inbound.test.ts +508 -0
- package/src/inbound.ts +278 -0
- package/src/llm-context-debug.test.ts +55 -0
- package/src/llm-context-debug.ts +139 -0
- package/src/login.runtime.test.ts +737 -0
- package/src/login.runtime.ts +277 -0
- package/src/manifest.test.ts +352 -0
- package/src/media-runtime.test.ts +207 -0
- package/src/media-runtime.ts +152 -0
- package/src/message-mapper.test.ts +201 -0
- package/src/message-mapper.ts +174 -0
- package/src/mock-transport.test.ts +35 -0
- package/src/mock-transport.ts +38 -0
- package/src/outbound.test.ts +1269 -0
- package/src/outbound.ts +803 -0
- package/src/plugin-entry.test.ts +38 -0
- package/src/plugin-prompts.test.ts +94 -0
- package/src/plugin-prompts.ts +107 -0
- package/src/profile-prompt.test.ts +274 -0
- package/src/profile-prompt.ts +351 -0
- package/src/profile-sync.test.ts +539 -0
- package/src/profile-sync.ts +191 -0
- package/src/prompt-injection.test.ts +39 -0
- package/src/prompt-injection.ts +45 -0
- package/src/protocol-types.test.ts +69 -0
- package/src/protocol-types.ts +296 -0
- package/src/protocol-types.typecheck.ts +89 -0
- package/src/protocol.test.ts +39 -0
- package/src/protocol.ts +42 -0
- package/src/reply-dispatcher.test.ts +1324 -0
- package/src/reply-dispatcher.ts +555 -0
- package/src/runtime.test.ts +4719 -0
- package/src/runtime.ts +1493 -0
- package/src/scripts.test.ts +85 -0
- package/src/storage.test.ts +560 -0
- package/src/storage.ts +807 -0
- package/src/terminal-send.test.ts +81 -0
- package/src/terminal-send.ts +56 -0
- package/src/tools-schema.ts +337 -0
- package/src/tools.test.ts +933 -0
- package/src/tools.ts +1185 -0
- package/src/ws-alignment.test.ts +103 -0
- package/src/ws-alignment.ts +275 -0
- package/src/ws-client.test.ts +1217 -0
- package/src/ws-client.ts +662 -0
- package/src/ws-log.test.ts +32 -0
- package/src/ws-log.ts +31 -0
package/src/commands.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { OpenClawPluginApi } from "openclaw/plugin-sdk";
|
|
2
|
+
import type { OpenclawClawchatMutateConfigFile } from "./login.runtime.ts";
|
|
3
|
+
|
|
4
|
+
function extractInviteCode(value: unknown): string {
|
|
5
|
+
const raw = typeof value === "string" ? value.trim() : "";
|
|
6
|
+
return raw.match(/\b[A-Z0-9]{6}\b/u)?.[0] ?? "";
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
function errorMessage(err: unknown): string {
|
|
10
|
+
return err instanceof Error ? err.message : String(err);
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function registerOpenclawClawlingCommands(api: Pick<OpenClawPluginApi, "registerCommand" | "logger" | "runtime">): void {
|
|
14
|
+
api.registerCommand({
|
|
15
|
+
name: "clawchat-activate",
|
|
16
|
+
description: "Activate ClawChat with an invite code, e.g. /clawchat-activate A1B2C3.",
|
|
17
|
+
acceptsArgs: true,
|
|
18
|
+
requireAuth: true,
|
|
19
|
+
async handler(ctx) {
|
|
20
|
+
const code = extractInviteCode(ctx.args ?? ctx.commandBody);
|
|
21
|
+
if (!code) {
|
|
22
|
+
return { text: "ClawChat invite code is required. Usage: /clawchat-activate A1B2C3" };
|
|
23
|
+
}
|
|
24
|
+
try {
|
|
25
|
+
const { runOpenclawClawlingLogin } = await import("./login.runtime.ts");
|
|
26
|
+
await runOpenclawClawlingLogin({
|
|
27
|
+
cfg: ctx.config,
|
|
28
|
+
accountId: ctx.accountId ?? null,
|
|
29
|
+
runtime: { log: (message: string) => api.logger?.info?.(message) },
|
|
30
|
+
readInviteCode: async () => code,
|
|
31
|
+
mutateConfigFile: (api.runtime.config as unknown as {
|
|
32
|
+
mutateConfigFile: OpenclawClawchatMutateConfigFile;
|
|
33
|
+
}).mutateConfigFile,
|
|
34
|
+
});
|
|
35
|
+
return { text: "✅ ClawChat activated successfully." };
|
|
36
|
+
} catch (err) {
|
|
37
|
+
return { text: `❌ ${errorMessage(err)}` };
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
@@ -0,0 +1,344 @@
|
|
|
1
|
+
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/setup";
|
|
2
|
+
import { describe, expect, it } from "vitest";
|
|
3
|
+
import {
|
|
4
|
+
CHANNEL_ID,
|
|
5
|
+
DEFAULT_BASE_URL,
|
|
6
|
+
DEFAULT_WEBSOCKET_URL,
|
|
7
|
+
effectiveGroupCommandMode,
|
|
8
|
+
effectiveGroupMode,
|
|
9
|
+
mergeOpenclawClawchatToolAllow,
|
|
10
|
+
openclawClawlingConfigSchema,
|
|
11
|
+
resolveOpenclawClawlingAccount,
|
|
12
|
+
listOpenclawClawlingAccountIds,
|
|
13
|
+
} from "./config.ts";
|
|
14
|
+
|
|
15
|
+
describe("clawchat-plugin-openclaw config", () => {
|
|
16
|
+
it("uses correct channel id", () => {
|
|
17
|
+
expect(CHANNEL_ID).toBe("clawchat-plugin-openclaw");
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("resolves defaults when no config provided", () => {
|
|
21
|
+
const account = resolveOpenclawClawlingAccount({});
|
|
22
|
+
expect(account.accountId).toBe(DEFAULT_ACCOUNT_ID);
|
|
23
|
+
expect(account.enabled).toBe(true);
|
|
24
|
+
expect(account.configured).toBe(false);
|
|
25
|
+
expect(account).not.toHaveProperty("replyMode");
|
|
26
|
+
expect(account.groupMode).toBe("all");
|
|
27
|
+
expect(account.groupCommandMode).toBe("owner");
|
|
28
|
+
expect(account.forwardThinking).toBe(true);
|
|
29
|
+
expect(account.forwardToolCalls).toBe(false);
|
|
30
|
+
expect(account.richInteractions).toBe(false);
|
|
31
|
+
expect(account).not.toHaveProperty("stream");
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it("resolves required fields without reply mode or stream tuning", () => {
|
|
35
|
+
const cfg = {
|
|
36
|
+
channels: {
|
|
37
|
+
"clawchat-plugin-openclaw": {
|
|
38
|
+
websocketUrl: "wss://chat.example.com/ws",
|
|
39
|
+
token: "secret",
|
|
40
|
+
agentId: "agt-1",
|
|
41
|
+
userId: "agent-1",
|
|
42
|
+
ownerUserId: "owner-1",
|
|
43
|
+
forwardThinking: false,
|
|
44
|
+
forwardToolCalls: true,
|
|
45
|
+
richInteractions: true,
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
const account = resolveOpenclawClawlingAccount(cfg);
|
|
50
|
+
expect(account.configured).toBe(true);
|
|
51
|
+
expect(account.websocketUrl).toBe("wss://chat.example.com/ws");
|
|
52
|
+
expect(account.token).toBe("secret");
|
|
53
|
+
expect(account.agentId).toBe("agt-1");
|
|
54
|
+
expect(account.userId).toBe("agent-1");
|
|
55
|
+
expect(account.ownerUserId).toBe("owner-1");
|
|
56
|
+
expect(account).not.toHaveProperty("replyMode");
|
|
57
|
+
expect(account.forwardThinking).toBe(false);
|
|
58
|
+
expect(account.forwardToolCalls).toBe(true);
|
|
59
|
+
expect(account.richInteractions).toBe(true);
|
|
60
|
+
expect(account).not.toHaveProperty("stream");
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("does not use userId as an ownerUserId fallback", () => {
|
|
64
|
+
const account = resolveOpenclawClawlingAccount({
|
|
65
|
+
channels: {
|
|
66
|
+
"clawchat-plugin-openclaw": {
|
|
67
|
+
token: "secret",
|
|
68
|
+
userId: "agent-user-id",
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
expect(account.userId).toBe("agent-user-id");
|
|
74
|
+
expect(account.ownerUserId).not.toBe("agent-user-id");
|
|
75
|
+
expect(account.configured).toBe(false);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("resolves credentials from ClawChat environment variables when config omits them", () => {
|
|
79
|
+
const account = resolveOpenclawClawlingAccount(
|
|
80
|
+
{},
|
|
81
|
+
{
|
|
82
|
+
CLAWCHAT_TOKEN: "env-token",
|
|
83
|
+
CLAWCHAT_AGENT_ID: "env-agent",
|
|
84
|
+
CLAWCHAT_USER_ID: "env-user",
|
|
85
|
+
CLAWCHAT_OWNER_USER_ID: "env-owner",
|
|
86
|
+
CLAWCHAT_BASE_URL: "https://api.env.example",
|
|
87
|
+
CLAWCHAT_WEBSOCKET_URL: "wss://ws.env.example/ws",
|
|
88
|
+
},
|
|
89
|
+
);
|
|
90
|
+
|
|
91
|
+
expect(account.configured).toBe(true);
|
|
92
|
+
expect(account.token).toBe("env-token");
|
|
93
|
+
expect(account.agentId).toBe("env-agent");
|
|
94
|
+
expect(account.userId).toBe("env-user");
|
|
95
|
+
expect(account.ownerUserId).toBe("env-owner");
|
|
96
|
+
expect(account.baseUrl).toBe("https://api.env.example");
|
|
97
|
+
expect(account.websocketUrl).toBe("wss://ws.env.example/ws");
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("prefers explicit channel config over ClawChat environment variables", () => {
|
|
101
|
+
const account = resolveOpenclawClawlingAccount(
|
|
102
|
+
{
|
|
103
|
+
channels: {
|
|
104
|
+
"clawchat-plugin-openclaw": {
|
|
105
|
+
token: "config-token",
|
|
106
|
+
agentId: "config-agent",
|
|
107
|
+
userId: "config-user",
|
|
108
|
+
ownerUserId: "config-owner",
|
|
109
|
+
baseUrl: "https://api.config.example",
|
|
110
|
+
websocketUrl: "wss://ws.config.example/ws",
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
{
|
|
115
|
+
CLAWCHAT_TOKEN: "env-token",
|
|
116
|
+
CLAWCHAT_AGENT_ID: "env-agent",
|
|
117
|
+
CLAWCHAT_USER_ID: "env-user",
|
|
118
|
+
CLAWCHAT_OWNER_USER_ID: "env-owner",
|
|
119
|
+
CLAWCHAT_BASE_URL: "https://api.env.example",
|
|
120
|
+
CLAWCHAT_WEBSOCKET_URL: "wss://ws.env.example/ws",
|
|
121
|
+
},
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
expect(account.token).toBe("config-token");
|
|
125
|
+
expect(account.agentId).toBe("config-agent");
|
|
126
|
+
expect(account.userId).toBe("config-user");
|
|
127
|
+
expect(account.ownerUserId).toBe("config-owner");
|
|
128
|
+
expect(account.baseUrl).toBe("https://api.config.example");
|
|
129
|
+
expect(account.websocketUrl).toBe("wss://ws.config.example/ws");
|
|
130
|
+
});
|
|
131
|
+
|
|
132
|
+
it("does not publish replyMode in the channel config schema", () => {
|
|
133
|
+
expect(openclawClawlingConfigSchema.properties).not.toHaveProperty("replyMode");
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
it("does not publish stream tuning in the channel config schema", () => {
|
|
137
|
+
expect(openclawClawlingConfigSchema.properties).not.toHaveProperty("stream");
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
it("preserves explicit mention groupMode", () => {
|
|
141
|
+
const cfg = {
|
|
142
|
+
channels: {
|
|
143
|
+
"clawchat-plugin-openclaw": {
|
|
144
|
+
websocketUrl: "w",
|
|
145
|
+
token: "t",
|
|
146
|
+
userId: "a",
|
|
147
|
+
ownerUserId: "o",
|
|
148
|
+
groupMode: "mention",
|
|
149
|
+
},
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
const account = resolveOpenclawClawlingAccount(cfg);
|
|
153
|
+
expect(account.groupMode).toBe("mention");
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
it("falls back to all groupMode for unknown values", () => {
|
|
157
|
+
const cfg = {
|
|
158
|
+
channels: {
|
|
159
|
+
"clawchat-plugin-openclaw": {
|
|
160
|
+
websocketUrl: "w",
|
|
161
|
+
token: "t",
|
|
162
|
+
userId: "a",
|
|
163
|
+
ownerUserId: "o",
|
|
164
|
+
groupMode: "weird",
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
};
|
|
168
|
+
const account = resolveOpenclawClawlingAccount(cfg);
|
|
169
|
+
expect(account.groupMode).toBe("all");
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
it("resolves per-group groupMode overrides", () => {
|
|
173
|
+
const account = resolveOpenclawClawlingAccount({
|
|
174
|
+
channels: {
|
|
175
|
+
"clawchat-plugin-openclaw": {
|
|
176
|
+
groups: {
|
|
177
|
+
"group-1": { groupMode: "mention" },
|
|
178
|
+
"*": { groupMode: "all" },
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
expect(account.groups).toEqual({
|
|
185
|
+
"group-1": { groupMode: "mention", groupCommandMode: "owner" },
|
|
186
|
+
"*": { groupMode: "all", groupCommandMode: "owner" },
|
|
187
|
+
});
|
|
188
|
+
expect(effectiveGroupMode(account, "group-1")).toBe("mention");
|
|
189
|
+
expect(effectiveGroupMode(account, "group-2")).toBe("all");
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
it("resolves groupCommandMode and per-group overrides", () => {
|
|
193
|
+
const account = resolveOpenclawClawlingAccount({
|
|
194
|
+
channels: {
|
|
195
|
+
"clawchat-plugin-openclaw": {
|
|
196
|
+
groupCommandMode: "off",
|
|
197
|
+
groups: {
|
|
198
|
+
"group-open": { groupCommandMode: "all" },
|
|
199
|
+
"*": { groupCommandMode: "owner" },
|
|
200
|
+
},
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
expect(account.groupCommandMode).toBe("off");
|
|
206
|
+
expect(account.groups).toEqual({
|
|
207
|
+
"group-open": { groupMode: "all", groupCommandMode: "all" },
|
|
208
|
+
"*": { groupMode: "all", groupCommandMode: "owner" },
|
|
209
|
+
});
|
|
210
|
+
expect(effectiveGroupCommandMode(account, "group-open")).toBe("all");
|
|
211
|
+
expect(effectiveGroupCommandMode(account, "group-other")).toBe("owner");
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
it("normalizes invalid groupCommandMode values to owner", () => {
|
|
215
|
+
const account = resolveOpenclawClawlingAccount({
|
|
216
|
+
channels: {
|
|
217
|
+
"clawchat-plugin-openclaw": {
|
|
218
|
+
groupCommandMode: "weird",
|
|
219
|
+
groups: {
|
|
220
|
+
"group-weird": { groupCommandMode: "weird" },
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
expect(account.groupCommandMode).toBe("owner");
|
|
227
|
+
expect(account.groups["group-weird"]?.groupCommandMode).toBe("owner");
|
|
228
|
+
expect(effectiveGroupCommandMode(account, "group-weird")).toBe("owner");
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
it("lets exact per-group groupMode win over wildcard and channel defaults", () => {
|
|
232
|
+
const account = resolveOpenclawClawlingAccount({
|
|
233
|
+
channels: {
|
|
234
|
+
"clawchat-plugin-openclaw": {
|
|
235
|
+
groupMode: "mention",
|
|
236
|
+
groups: {
|
|
237
|
+
"group-open": { groupMode: "all" },
|
|
238
|
+
"*": { groupMode: "mention" },
|
|
239
|
+
},
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
expect(effectiveGroupMode(account, "group-open")).toBe("all");
|
|
245
|
+
expect(effectiveGroupMode(account, "group-other")).toBe("mention");
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
it("normalizes invalid per-group groupMode values to all", () => {
|
|
249
|
+
const account = resolveOpenclawClawlingAccount({
|
|
250
|
+
channels: {
|
|
251
|
+
"clawchat-plugin-openclaw": {
|
|
252
|
+
groupMode: "mention",
|
|
253
|
+
groups: {
|
|
254
|
+
"group-weird": { groupMode: "weird" },
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
},
|
|
258
|
+
});
|
|
259
|
+
|
|
260
|
+
expect(account.groups["group-weird"]?.groupMode).toBe("all");
|
|
261
|
+
expect(effectiveGroupMode(account, "group-weird")).toBe("all");
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
it("lists the default account id", () => {
|
|
265
|
+
expect(listOpenclawClawlingAccountIds()).toEqual([DEFAULT_ACCOUNT_ID]);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
it("parses baseUrl when provided", () => {
|
|
269
|
+
const cfg = {
|
|
270
|
+
channels: {
|
|
271
|
+
"clawchat-plugin-openclaw": {
|
|
272
|
+
websocketUrl: "wss://w",
|
|
273
|
+
token: "t",
|
|
274
|
+
userId: "u",
|
|
275
|
+
ownerUserId: "o",
|
|
276
|
+
baseUrl: "https://api.example.com",
|
|
277
|
+
},
|
|
278
|
+
},
|
|
279
|
+
};
|
|
280
|
+
const account = resolveOpenclawClawlingAccount(cfg);
|
|
281
|
+
expect(account.baseUrl).toBe("https://api.example.com");
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
it("falls back to the built-in DEFAULT_BASE_URL when unset", async () => {
|
|
285
|
+
const account = resolveOpenclawClawlingAccount({});
|
|
286
|
+
expect(account.baseUrl).toBe(DEFAULT_BASE_URL);
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
it("falls back to the built-in DEFAULT_WEBSOCKET_URL when unset", async () => {
|
|
290
|
+
const account = resolveOpenclawClawlingAccount({});
|
|
291
|
+
expect(account.websocketUrl).toBe(DEFAULT_WEBSOCKET_URL);
|
|
292
|
+
});
|
|
293
|
+
|
|
294
|
+
it("uses the production ClawChat service as the built-in fallback endpoint", () => {
|
|
295
|
+
expect(DEFAULT_BASE_URL).toBe("https://app.clawling.com");
|
|
296
|
+
expect(DEFAULT_WEBSOCKET_URL).toBe("wss://app.clawling.com/ws");
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it("does NOT include baseUrl in the configured predicate (channel still works without it)", async () => {
|
|
300
|
+
const cfg = {
|
|
301
|
+
channels: {
|
|
302
|
+
"clawchat-plugin-openclaw": {
|
|
303
|
+
websocketUrl: "wss://w",
|
|
304
|
+
token: "t",
|
|
305
|
+
userId: "u",
|
|
306
|
+
ownerUserId: "o",
|
|
307
|
+
// no baseUrl — resolver uses default
|
|
308
|
+
},
|
|
309
|
+
},
|
|
310
|
+
};
|
|
311
|
+
const account = resolveOpenclawClawlingAccount(cfg);
|
|
312
|
+
expect(account.configured).toBe(true);
|
|
313
|
+
expect(account.baseUrl).toBe(DEFAULT_BASE_URL);
|
|
314
|
+
});
|
|
315
|
+
|
|
316
|
+
it("adds the plugin to tools.alsoAllow even when an explicit allowlist is already in use", () => {
|
|
317
|
+
const cfg = mergeOpenclawClawchatToolAllow({
|
|
318
|
+
tools: {
|
|
319
|
+
allow: ["bash"],
|
|
320
|
+
deny: ["exec"],
|
|
321
|
+
},
|
|
322
|
+
} as never) as { tools: Record<string, unknown> };
|
|
323
|
+
|
|
324
|
+
expect(cfg.tools.allow).toEqual(["bash"]);
|
|
325
|
+
expect(cfg.tools.deny).toEqual(["exec"]);
|
|
326
|
+
expect(cfg.tools.alsoAllow).toEqual(["clawchat-plugin-openclaw"]);
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
it("adds the plugin to tools.alsoAllow when no explicit allowlist is in use", () => {
|
|
330
|
+
const cfg = mergeOpenclawClawchatToolAllow({
|
|
331
|
+
tools: {
|
|
332
|
+
profile: "coding",
|
|
333
|
+
allow: [],
|
|
334
|
+
},
|
|
335
|
+
} as never) as { tools: Record<string, unknown> };
|
|
336
|
+
|
|
337
|
+
expect(cfg.tools).toEqual({
|
|
338
|
+
profile: "coding",
|
|
339
|
+
allow: [],
|
|
340
|
+
alsoAllow: ["clawchat-plugin-openclaw"],
|
|
341
|
+
});
|
|
342
|
+
});
|
|
343
|
+
|
|
344
|
+
});
|