@openclaw/synology-chat 2026.7.1 → 2026.7.2-beta.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/api.js +1 -1
- package/dist/{channel-C6bhvNZi.js → channel-Hiv3SX8l.js} +57 -40
- package/dist/channel-plugin-api.js +1 -1
- package/dist/setup-api.js +1 -1
- package/dist/{setup-surface-pMbKFqU5.js → setup-surface-CJtfU_Gw.js} +20 -24
- package/npm-shrinkwrap.json +2 -2
- package/package.json +4 -4
package/dist/api.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as setSynologyRuntime, t as synologyChatPlugin } from "./channel-
|
|
1
|
+
import { n as setSynologyRuntime, t as synologyChatPlugin } from "./channel-Hiv3SX8l.js";
|
|
2
2
|
import { t as collectSynologyChatSecurityAuditFindings } from "./security-audit-DIsaxIaB.js";
|
|
3
3
|
export { collectSynologyChatSecurityAuditFindings, setSynologyRuntime, synologyChatPlugin };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { i as resolveAccount, n as synologyChatSetupWizard, r as listAccountIds, t as synologyChatSetupAdapter } from "./setup-surface-
|
|
1
|
+
import { i as resolveAccount, n as synologyChatSetupWizard, r as listAccountIds, t as synologyChatSetupAdapter } from "./setup-surface-CJtfU_Gw.js";
|
|
2
2
|
import { t as collectSynologyChatSecurityAuditFindings } from "./security-audit-DIsaxIaB.js";
|
|
3
3
|
import { DEFAULT_ACCOUNT_ID } from "openclaw/plugin-sdk/account-id";
|
|
4
4
|
import { createHybridChannelConfigAdapter, createScopedDmSecurityResolver } from "openclaw/plugin-sdk/channel-config-helpers";
|
|
@@ -8,16 +8,18 @@ import { composeWarningCollectors, createConditionalWarningCollector, projectAcc
|
|
|
8
8
|
import { createEmptyChannelDirectoryAdapter } from "openclaw/plugin-sdk/directory-runtime";
|
|
9
9
|
import { finiteSecondsToTimerSafeMilliseconds, parseStrictNonNegativeInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
10
10
|
import { normalizeLowercaseStringOrEmpty, normalizeStringEntriesLower } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
11
|
+
import { sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
|
|
11
12
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1 } from "openclaw/plugin-sdk/account-resolution";
|
|
12
|
-
import {
|
|
13
|
+
import { createChannelApprovalAuth } from "openclaw/plugin-sdk/approval-auth-runtime";
|
|
13
14
|
import * as http from "node:http";
|
|
14
15
|
import * as https from "node:https";
|
|
15
16
|
import { safeParseJsonWithSchema, safeParseWithSchema } from "openclaw/plugin-sdk/extension-shared";
|
|
17
|
+
import { readByteStreamWithLimit } from "openclaw/plugin-sdk/response-limit-runtime";
|
|
16
18
|
import { sleep } from "openclaw/plugin-sdk/runtime-env";
|
|
17
19
|
import { formatErrorMessage, resolvePinnedHostnameWithPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
18
20
|
import { z } from "zod";
|
|
19
21
|
import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
|
|
20
|
-
import { beginWebhookRequestPipelineOrReject, createFixedWindowRateLimiter, createWebhookInFlightLimiter, isRequestBodyLimitError, readRequestBodyWithLimit, registerPluginHttpRoute, requestBodyErrorToText } from "openclaw/plugin-sdk/webhook-ingress";
|
|
22
|
+
import { beginWebhookRequestPipelineOrReject, createFixedWindowRateLimiter, createWebhookInFlightLimiter, isRequestBodyLimitError, readRequestBodyWithLimit, registerPluginHttpRoute, requestBodyErrorToText, resolveRequestClientIp } from "openclaw/plugin-sdk/webhook-ingress";
|
|
21
23
|
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
|
22
24
|
import { buildAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
|
23
25
|
import * as querystring from "node:querystring";
|
|
@@ -29,16 +31,13 @@ function normalizeSynologyChatApproverId(value) {
|
|
|
29
31
|
const trimmed = String(value).trim();
|
|
30
32
|
return /^\d+$/.test(trimmed) ? trimmed : void 0;
|
|
31
33
|
}
|
|
32
|
-
const synologyChatApprovalAuth =
|
|
34
|
+
const synologyChatApprovalAuth = createChannelApprovalAuth({
|
|
33
35
|
channelLabel: "Synology Chat",
|
|
34
|
-
|
|
35
|
-
return
|
|
36
|
-
allowFrom: resolveAccount(cfg ?? {}, accountId).allowedUserIds,
|
|
37
|
-
normalizeApprover: normalizeSynologyChatApproverId
|
|
38
|
-
});
|
|
36
|
+
resolveInputs: ({ cfg, accountId }) => {
|
|
37
|
+
return { allowFrom: resolveAccount(cfg ?? {}, accountId).allowedUserIds };
|
|
39
38
|
},
|
|
40
|
-
|
|
41
|
-
});
|
|
39
|
+
normalizeApprover: normalizeSynologyChatApproverId
|
|
40
|
+
}).approvalAuth;
|
|
42
41
|
//#endregion
|
|
43
42
|
//#region extensions/synology-chat/src/client.ts
|
|
44
43
|
/**
|
|
@@ -46,6 +45,8 @@ const synologyChatApprovalAuth = createResolvedApproverActionAuthAdapter({
|
|
|
46
45
|
* Sends messages TO Synology Chat via the incoming webhook URL.
|
|
47
46
|
*/
|
|
48
47
|
const MIN_SEND_INTERVAL_MS = 500;
|
|
48
|
+
/** user_list JSON can be larger than inbound webhook pre-auth payloads. */
|
|
49
|
+
const USER_LIST_RESPONSE_MAX_BYTES = 1 * 1024 * 1024;
|
|
49
50
|
let lastSendTime = 0;
|
|
50
51
|
let sendQueue = Promise.resolve();
|
|
51
52
|
const ChatUserSchema = z.object({
|
|
@@ -129,29 +130,36 @@ async function fetchChatUsers(incomingUrl, allowInsecureSsl = false, log) {
|
|
|
129
130
|
const transport = parsedUrl.protocol === "https:" ? https : http;
|
|
130
131
|
const requestOptions = parsedUrl.protocol === "https:" ? { rejectUnauthorized: !allowInsecureSsl } : {};
|
|
131
132
|
const req = transport.get(listUrl, requestOptions, (res) => {
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
const result = safeParseJsonWithSchema(ChatUserListResponseSchema, data);
|
|
138
|
-
if (!result) {
|
|
139
|
-
log?.warn("fetchChatUsers: failed to parse user_list response");
|
|
140
|
-
finish(cached?.users ?? []);
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
if (result.success) {
|
|
144
|
-
const users = result.data?.users ?? [];
|
|
145
|
-
chatUserCache.set(listUrl, {
|
|
146
|
-
users,
|
|
147
|
-
cachedAt: now
|
|
133
|
+
(async () => {
|
|
134
|
+
try {
|
|
135
|
+
const data = await readByteStreamWithLimit(res, {
|
|
136
|
+
maxBytes: USER_LIST_RESPONSE_MAX_BYTES,
|
|
137
|
+
onOverflow: ({ maxBytes }) => /* @__PURE__ */ new Error(`user_list response exceeded ${maxBytes} bytes`)
|
|
148
138
|
});
|
|
149
|
-
|
|
150
|
-
|
|
139
|
+
if (settled) return;
|
|
140
|
+
const result = safeParseJsonWithSchema(ChatUserListResponseSchema, data.toString("utf8"));
|
|
141
|
+
if (!result) {
|
|
142
|
+
log?.warn("fetchChatUsers: failed to parse user_list response");
|
|
143
|
+
finish(cached?.users ?? []);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (result.success) {
|
|
147
|
+
const users = result.data?.users ?? [];
|
|
148
|
+
chatUserCache.set(listUrl, {
|
|
149
|
+
users,
|
|
150
|
+
cachedAt: now
|
|
151
|
+
});
|
|
152
|
+
finish(users);
|
|
153
|
+
return;
|
|
154
|
+
}
|
|
155
|
+
log?.warn(`fetchChatUsers: API returned success=${result.success}, using cached data`);
|
|
156
|
+
finish(cached?.users ?? []);
|
|
157
|
+
} catch (err) {
|
|
158
|
+
if (settled) return;
|
|
159
|
+
log?.warn(`fetchChatUsers: ${formatErrorMessage(err)}, using cached data`);
|
|
160
|
+
finish(cached?.users ?? []);
|
|
151
161
|
}
|
|
152
|
-
|
|
153
|
-
finish(cached?.users ?? []);
|
|
154
|
-
});
|
|
162
|
+
})();
|
|
155
163
|
}).on("error", (err) => {
|
|
156
164
|
log?.warn(`fetchChatUsers: HTTP error — ${err instanceof Error ? err.message : err}`);
|
|
157
165
|
finish(cached?.users ?? []);
|
|
@@ -228,13 +236,10 @@ function doPost(url, body, allowInsecureSsl = false) {
|
|
|
228
236
|
timeout: 3e4,
|
|
229
237
|
rejectUnauthorized: !allowInsecureSsl
|
|
230
238
|
}, (res) => {
|
|
231
|
-
let data = "";
|
|
232
|
-
res.on("data", (chunk) => {
|
|
233
|
-
data += chunk.toString();
|
|
234
|
-
});
|
|
235
239
|
res.on("end", () => {
|
|
236
240
|
resolve(res.statusCode === 200);
|
|
237
241
|
});
|
|
242
|
+
res.resume();
|
|
238
243
|
});
|
|
239
244
|
req.on("error", reject);
|
|
240
245
|
req.on("timeout", () => {
|
|
@@ -554,8 +559,8 @@ function getInvalidTokenRateLimiter(account) {
|
|
|
554
559
|
}
|
|
555
560
|
return rl;
|
|
556
561
|
}
|
|
557
|
-
function getSynologyWebhookInvalidTokenRateLimitKey(
|
|
558
|
-
return req.socket?.remoteAddress ?? "unknown";
|
|
562
|
+
function getSynologyWebhookInvalidTokenRateLimitKey(params) {
|
|
563
|
+
return resolveRequestClientIp(params.req, params.trustedProxies, params.allowRealIpFallback === true) ?? params.req.socket?.remoteAddress ?? "unknown";
|
|
559
564
|
}
|
|
560
565
|
function getSynologyWebhookInFlightKey(account) {
|
|
561
566
|
return account.accountId;
|
|
@@ -736,7 +741,11 @@ async function parseWebhookPayloadRequest(params) {
|
|
|
736
741
|
};
|
|
737
742
|
}
|
|
738
743
|
async function authorizeSynologyWebhook(params) {
|
|
739
|
-
const invalidTokenRateLimitKey = getSynologyWebhookInvalidTokenRateLimitKey(
|
|
744
|
+
const invalidTokenRateLimitKey = getSynologyWebhookInvalidTokenRateLimitKey({
|
|
745
|
+
req: params.req,
|
|
746
|
+
trustedProxies: params.trustedProxies,
|
|
747
|
+
allowRealIpFallback: params.allowRealIpFallback
|
|
748
|
+
});
|
|
740
749
|
if (params.invalidTokenRateLimiter.isLocked(invalidTokenRateLimitKey)) {
|
|
741
750
|
params.log?.warn(`Rate limit exceeded for remote IP: ${invalidTokenRateLimitKey}`);
|
|
742
751
|
return {
|
|
@@ -815,6 +824,8 @@ async function parseAndAuthorizeSynologyWebhook(params) {
|
|
|
815
824
|
payload: parsed.payload,
|
|
816
825
|
invalidTokenRateLimiter: params.invalidTokenRateLimiter,
|
|
817
826
|
rateLimiter: params.rateLimiter,
|
|
827
|
+
trustedProxies: params.trustedProxies,
|
|
828
|
+
allowRealIpFallback: params.allowRealIpFallback,
|
|
818
829
|
log: params.log
|
|
819
830
|
});
|
|
820
831
|
if (!authorized.ok) {
|
|
@@ -902,6 +913,8 @@ function createWebhookHandler(deps) {
|
|
|
902
913
|
account,
|
|
903
914
|
invalidTokenRateLimiter,
|
|
904
915
|
rateLimiter,
|
|
916
|
+
trustedProxies: deps.trustedProxies,
|
|
917
|
+
allowRealIpFallback: deps.allowRealIpFallback,
|
|
905
918
|
log,
|
|
906
919
|
bodyTimeoutMs: deps.bodyTimeoutMs
|
|
907
920
|
});
|
|
@@ -988,7 +1001,7 @@ function validateSynologyGatewayAccountStartup(params) {
|
|
|
988
1001
|
return { ok: true };
|
|
989
1002
|
}
|
|
990
1003
|
function registerSynologyWebhookRoute(params) {
|
|
991
|
-
const { account, log } = params;
|
|
1004
|
+
const { cfg, account, log } = params;
|
|
992
1005
|
const routeKey = getRouteKey(account);
|
|
993
1006
|
const prevUnregister = activeRouteUnregisters.get(routeKey);
|
|
994
1007
|
if (prevUnregister) {
|
|
@@ -998,6 +1011,8 @@ function registerSynologyWebhookRoute(params) {
|
|
|
998
1011
|
}
|
|
999
1012
|
const handler = createWebhookHandler({
|
|
1000
1013
|
account,
|
|
1014
|
+
trustedProxies: cfg.gateway?.trustedProxies,
|
|
1015
|
+
allowRealIpFallback: cfg.gateway?.allowRealIpFallback === true,
|
|
1001
1016
|
deliver: async (msg) => await dispatchSynologyChatInboundEvent({
|
|
1002
1017
|
account,
|
|
1003
1018
|
msg,
|
|
@@ -1198,6 +1213,7 @@ function createSynologyChatPlugin() {
|
|
|
1198
1213
|
}).ok) return waitUntilAbort(abortSignal);
|
|
1199
1214
|
log?.info?.(`Starting Synology Chat channel (account: ${accountId}, path: ${account.webhookPath})`);
|
|
1200
1215
|
const unregister = registerSynologyWebhookRoute({
|
|
1216
|
+
cfg,
|
|
1201
1217
|
account,
|
|
1202
1218
|
accountId,
|
|
1203
1219
|
log
|
|
@@ -1255,6 +1271,7 @@ function createSynologyChatPlugin() {
|
|
|
1255
1271
|
outbound: {
|
|
1256
1272
|
deliveryMode: "gateway",
|
|
1257
1273
|
textChunkLimit: 2e3,
|
|
1274
|
+
sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text),
|
|
1258
1275
|
sendText: sendSynologyChatText,
|
|
1259
1276
|
sendMedia: async (ctx) => {
|
|
1260
1277
|
if (!ctx.mediaUrl) throw new Error("Synology Chat media send requires mediaUrl");
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as synologyChatPlugin } from "./channel-
|
|
1
|
+
import { t as synologyChatPlugin } from "./channel-Hiv3SX8l.js";
|
|
2
2
|
export { synologyChatPlugin };
|
package/dist/setup-api.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { n as synologyChatSetupWizard, t as synologyChatSetupAdapter } from "./setup-surface-
|
|
1
|
+
import { n as synologyChatSetupWizard, t as synologyChatSetupAdapter } from "./setup-surface-CJtfU_Gw.js";
|
|
2
2
|
export { synologyChatSetupAdapter, synologyChatSetupWizard };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { parseStrictInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
2
2
|
import { normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
3
|
-
import { DEFAULT_ACCOUNT_ID, listCombinedAccountIds, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
3
|
+
import { DEFAULT_ACCOUNT_ID, hasConfiguredAccountValue, listCombinedAccountIds, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
4
4
|
import { resolveDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
|
|
5
|
-
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, createAllowFromSection, createSetupTranslator, createStandardChannelSetupStatus, formatDocsLink, mergeAllowFromEntries, normalizeAccountId, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|
|
5
|
+
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, createAllowFromSection, createSetupTranslator, createStandardChannelSetupStatus, defineTokenCredential, formatDocsLink, mergeAllowFromEntries, normalizeAccountId, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|
|
6
6
|
//#region extensions/synology-chat/src/accounts.ts
|
|
7
7
|
/**
|
|
8
8
|
* Account resolution: reads config from channels.synology-chat,
|
|
@@ -13,7 +13,7 @@ function getChannelConfig$1(cfg) {
|
|
|
13
13
|
return cfg?.channels?.["synology-chat"];
|
|
14
14
|
}
|
|
15
15
|
function resolveImplicitAccountId(channelCfg) {
|
|
16
|
-
return channelCfg.token || process.env.SYNOLOGY_CHAT_TOKEN ? DEFAULT_ACCOUNT_ID : void 0;
|
|
16
|
+
return hasConfiguredAccountValue(channelCfg.token) || hasConfiguredAccountValue(process.env.SYNOLOGY_CHAT_TOKEN) ? DEFAULT_ACCOUNT_ID : void 0;
|
|
17
17
|
}
|
|
18
18
|
function getRawAccountConfig$1(channelCfg, accountId) {
|
|
19
19
|
if (accountId === DEFAULT_ACCOUNT_ID) return channelCfg;
|
|
@@ -238,8 +238,9 @@ const synologyChatSetupWizard = {
|
|
|
238
238
|
title: t("wizard.synologyChat.setupTitle"),
|
|
239
239
|
lines: SYNOLOGY_SETUP_HELP_LINES
|
|
240
240
|
},
|
|
241
|
-
credentials: [{
|
|
241
|
+
credentials: [defineTokenCredential({
|
|
242
242
|
inputKey: "token",
|
|
243
|
+
configKey: "token",
|
|
243
244
|
providerHint: channel,
|
|
244
245
|
credentialLabel: "outgoing webhook token",
|
|
245
246
|
preferredEnvVar: "SYNOLOGY_CHAT_TOKEN",
|
|
@@ -249,30 +250,25 @@ const synologyChatSetupWizard = {
|
|
|
249
250
|
keepPrompt: t("wizard.synologyChat.tokenKeep"),
|
|
250
251
|
inputPrompt: t("wizard.synologyChat.tokenInput"),
|
|
251
252
|
allowEnv: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID$1,
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
accountConfigured: isSynologyChatConfigured(cfg, accountId),
|
|
257
|
-
hasConfiguredValue: Boolean(normalizeOptionalString(raw.token)),
|
|
258
|
-
resolvedValue: normalizeOptionalString(account.token),
|
|
259
|
-
envValue: accountId === DEFAULT_ACCOUNT_ID$1 ? normalizeOptionalString(process.env.SYNOLOGY_CHAT_TOKEN) : void 0
|
|
260
|
-
};
|
|
261
|
-
},
|
|
262
|
-
applyUseEnv: async ({ cfg, accountId }) => patchSynologyChatAccountConfig({
|
|
263
|
-
cfg,
|
|
264
|
-
accountId,
|
|
265
|
-
enabled: true,
|
|
266
|
-
clearFields: ["token"],
|
|
267
|
-
patch: {}
|
|
253
|
+
resolveAccount: ({ cfg, accountId }) => ({
|
|
254
|
+
config: getRawAccountConfig(cfg, accountId),
|
|
255
|
+
resolved: resolveAccount(cfg, accountId),
|
|
256
|
+
configured: isSynologyChatConfigured(cfg, accountId)
|
|
268
257
|
}),
|
|
269
|
-
|
|
258
|
+
accountConfigured: (account) => account.configured,
|
|
259
|
+
hasConfiguredValue: (account) => Boolean(normalizeOptionalString(account.config.token)),
|
|
260
|
+
resolvedValue: (account) => normalizeOptionalString(account.resolved.token),
|
|
261
|
+
envValue: ({ accountId }) => accountId === DEFAULT_ACCOUNT_ID$1 ? normalizeOptionalString(process.env.SYNOLOGY_CHAT_TOKEN) : void 0,
|
|
262
|
+
patchAccount: ({ cfg, accountId, patch, clearFields }) => patchSynologyChatAccountConfig({
|
|
270
263
|
cfg,
|
|
271
264
|
accountId,
|
|
272
265
|
enabled: true,
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
266
|
+
clearFields,
|
|
267
|
+
patch
|
|
268
|
+
}),
|
|
269
|
+
useEnv: { clearFields: ["token"] },
|
|
270
|
+
set: { value: "resolved" }
|
|
271
|
+
})],
|
|
276
272
|
textInputs: [{
|
|
277
273
|
inputKey: "url",
|
|
278
274
|
message: t("wizard.synologyChat.incomingWebhookUrlPrompt"),
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/synology-chat",
|
|
3
|
-
"version": "2026.7.
|
|
3
|
+
"version": "2026.7.2-beta.2",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@openclaw/synology-chat",
|
|
9
|
-
"version": "2026.7.
|
|
9
|
+
"version": "2026.7.2-beta.2",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"zod": "4.4.3"
|
|
12
12
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/synology-chat",
|
|
3
|
-
"version": "2026.7.
|
|
3
|
+
"version": "2026.7.2-beta.2",
|
|
4
4
|
"description": "Synology Chat channel plugin for OpenClaw channels and direct messages.",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -27,10 +27,10 @@
|
|
|
27
27
|
"minHostVersion": ">=2026.4.10"
|
|
28
28
|
},
|
|
29
29
|
"compat": {
|
|
30
|
-
"pluginApi": ">=2026.7.
|
|
30
|
+
"pluginApi": ">=2026.7.2-beta.2"
|
|
31
31
|
},
|
|
32
32
|
"build": {
|
|
33
|
-
"openclawVersion": "2026.7.
|
|
33
|
+
"openclawVersion": "2026.7.2-beta.2"
|
|
34
34
|
},
|
|
35
35
|
"release": {
|
|
36
36
|
"publishToClawHub": true,
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"README.md"
|
|
52
52
|
],
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"openclaw": ">=2026.7.
|
|
54
|
+
"openclaw": ">=2026.7.2-beta.2"
|
|
55
55
|
},
|
|
56
56
|
"peerDependenciesMeta": {
|
|
57
57
|
"openclaw": {
|