@openclaw/synology-chat 2026.5.7 → 2026.5.10-beta.1
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
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-IPqYKUxY.js";
|
|
2
2
|
import { t as collectSynologyChatSecurityAuditFindings } from "./security-audit-Zu_nkF2x.js";
|
|
3
3
|
export { collectSynologyChatSecurityAuditFindings, setSynologyRuntime, synologyChatPlugin };
|
|
@@ -1,25 +1,27 @@
|
|
|
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-daP5yN4Y.js";
|
|
2
2
|
import { t as collectSynologyChatSecurityAuditFindings } from "./security-audit-Zu_nkF2x.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";
|
|
5
5
|
import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
|
|
6
6
|
import { waitUntilAbort } from "openclaw/plugin-sdk/channel-lifecycle";
|
|
7
|
+
import { createMessageReceiptFromOutboundResults, defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-message";
|
|
7
8
|
import { composeWarningCollectors, createConditionalWarningCollector, projectAccountConfigWarningCollector, projectAccountWarningCollector } from "openclaw/plugin-sdk/channel-policy";
|
|
8
|
-
import { attachChannelToResult } from "openclaw/plugin-sdk/channel-send-result";
|
|
9
9
|
import { createEmptyChannelDirectoryAdapter } from "openclaw/plugin-sdk/directory-runtime";
|
|
10
|
+
import { normalizeLowercaseStringOrEmpty } from "openclaw/plugin-sdk/text-runtime";
|
|
10
11
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1 } from "openclaw/plugin-sdk/account-resolution";
|
|
11
12
|
import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
|
|
12
13
|
import * as http from "node:http";
|
|
13
14
|
import * as https from "node:https";
|
|
14
15
|
import { safeParseJsonWithSchema, safeParseWithSchema } from "openclaw/plugin-sdk/extension-shared";
|
|
16
|
+
import { sleep } from "openclaw/plugin-sdk/runtime-env";
|
|
15
17
|
import { formatErrorMessage, resolvePinnedHostnameWithPolicy } from "openclaw/plugin-sdk/ssrf-runtime";
|
|
16
|
-
import { z } from "zod";
|
|
18
|
+
import { z } from "openclaw/plugin-sdk/zod";
|
|
17
19
|
import { buildChannelConfigSchema } from "openclaw/plugin-sdk/channel-config-schema";
|
|
18
|
-
import { z as z$1 } from "openclaw/plugin-sdk/zod";
|
|
19
20
|
import { beginWebhookRequestPipelineOrReject, createFixedWindowRateLimiter, createWebhookInFlightLimiter, isRequestBodyLimitError, readRequestBodyWithLimit, registerPluginHttpRoute, requestBodyErrorToText } from "openclaw/plugin-sdk/webhook-ingress";
|
|
20
21
|
import { createPluginRuntimeStore } from "openclaw/plugin-sdk/runtime-store";
|
|
21
22
|
import { buildAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
|
22
23
|
import * as querystring from "node:querystring";
|
|
24
|
+
import { resolveStableChannelMessageIngress } from "openclaw/plugin-sdk/channel-ingress-runtime";
|
|
23
25
|
import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
|
|
24
26
|
//#region extensions/synology-chat/src/approval-auth.ts
|
|
25
27
|
function normalizeSynologyChatApproverId(value) {
|
|
@@ -44,9 +46,6 @@ const synologyChatApprovalAuth = createResolvedApproverActionAuthAdapter({
|
|
|
44
46
|
*/
|
|
45
47
|
const MIN_SEND_INTERVAL_MS = 500;
|
|
46
48
|
let lastSendTime = 0;
|
|
47
|
-
function normalizeLowercaseStringOrEmpty$2(value) {
|
|
48
|
-
return typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
49
|
-
}
|
|
50
49
|
const ChatUserSchema = z.object({
|
|
51
50
|
user_id: z.number(),
|
|
52
51
|
username: z.string().optional(),
|
|
@@ -179,10 +178,10 @@ async function assertSafeWebhookFileUrl(fileUrl) {
|
|
|
179
178
|
*/
|
|
180
179
|
async function resolveLegacyWebhookNameToChatUserId(params) {
|
|
181
180
|
const users = await fetchChatUsers(params.incomingUrl, params.allowInsecureSsl, params.log);
|
|
182
|
-
const lower = normalizeLowercaseStringOrEmpty
|
|
183
|
-
const byNickname = users.find((u) => normalizeLowercaseStringOrEmpty
|
|
181
|
+
const lower = normalizeLowercaseStringOrEmpty(params.mutableWebhookUsername);
|
|
182
|
+
const byNickname = users.find((u) => normalizeLowercaseStringOrEmpty(u.nickname) === lower);
|
|
184
183
|
if (byNickname) return byNickname.user_id;
|
|
185
|
-
const byUsername = users.find((u) => normalizeLowercaseStringOrEmpty
|
|
184
|
+
const byUsername = users.find((u) => normalizeLowercaseStringOrEmpty(u.username) === lower);
|
|
186
185
|
if (byUsername) return byUsername.user_id;
|
|
187
186
|
}
|
|
188
187
|
function buildWebhookBody(payload, userId) {
|
|
@@ -230,14 +229,11 @@ function doPost(url, body, allowInsecureSsl = false) {
|
|
|
230
229
|
req.end();
|
|
231
230
|
});
|
|
232
231
|
}
|
|
233
|
-
function sleep(ms) {
|
|
234
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
235
|
-
}
|
|
236
232
|
//#endregion
|
|
237
233
|
//#region extensions/synology-chat/src/config-schema.ts
|
|
238
|
-
const SynologyChatChannelConfigSchema = buildChannelConfigSchema(z
|
|
239
|
-
dangerouslyAllowNameMatching: z
|
|
240
|
-
dangerouslyAllowInheritedWebhookPath: z
|
|
234
|
+
const SynologyChatChannelConfigSchema = buildChannelConfigSchema(z.object({
|
|
235
|
+
dangerouslyAllowNameMatching: z.boolean().optional(),
|
|
236
|
+
dangerouslyAllowInheritedWebhookPath: z.boolean().optional()
|
|
241
237
|
}).passthrough());
|
|
242
238
|
//#endregion
|
|
243
239
|
//#region extensions/synology-chat/src/runtime.ts
|
|
@@ -288,8 +284,8 @@ function resolveSynologyChatInboundRoute(params) {
|
|
|
288
284
|
}
|
|
289
285
|
async function deliverSynologyChatReply(params) {
|
|
290
286
|
const text = params.payload.text ?? params.payload.body;
|
|
291
|
-
if (!text) return;
|
|
292
|
-
await sendMessage(params.account.incomingUrl, text, params.sendUserId, params.account.allowInsecureSsl);
|
|
287
|
+
if (!text) return { visibleReplySent: false };
|
|
288
|
+
return { visibleReplySent: await sendMessage(params.account.incomingUrl, text, params.sendUserId, params.account.allowInsecureSsl) };
|
|
293
289
|
}
|
|
294
290
|
async function dispatchSynologyChatInboundTurn(params) {
|
|
295
291
|
const currentCfg = getSynologyRuntime().config.current();
|
|
@@ -364,13 +360,16 @@ async function dispatchSynologyChatInboundTurn(params) {
|
|
|
364
360
|
ctxPayload: msgCtx,
|
|
365
361
|
recordInboundSession: resolved.rt.channel.session.recordInboundSession,
|
|
366
362
|
dispatchReplyWithBufferedBlockDispatcher: resolved.rt.channel.reply.dispatchReplyWithBufferedBlockDispatcher,
|
|
367
|
-
delivery: {
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
363
|
+
delivery: {
|
|
364
|
+
durable: () => ({ to: sendUserId }),
|
|
365
|
+
deliver: async (payload) => {
|
|
366
|
+
return await deliverSynologyChatReply({
|
|
367
|
+
account: params.account,
|
|
368
|
+
sendUserId,
|
|
369
|
+
payload
|
|
370
|
+
});
|
|
371
|
+
}
|
|
372
|
+
},
|
|
374
373
|
dispatcherOptions: { onReplyStart: () => {
|
|
375
374
|
params.log?.info?.(`Agent reply started for ${params.msg.from}`);
|
|
376
375
|
} },
|
|
@@ -396,37 +395,23 @@ function validateToken(received, expected) {
|
|
|
396
395
|
if (!received || !expected) return false;
|
|
397
396
|
return safeEqualSecret(received, expected);
|
|
398
397
|
}
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
};
|
|
417
|
-
if (dmPolicy === "open") return checkUserAllowed(userId, allowedUserIds) ? { allowed: true } : {
|
|
418
|
-
allowed: false,
|
|
419
|
-
reason: "not-allowlisted"
|
|
420
|
-
};
|
|
421
|
-
if (allowedUserIds.length === 0) return {
|
|
422
|
-
allowed: false,
|
|
423
|
-
reason: "allowlist-empty"
|
|
424
|
-
};
|
|
425
|
-
if (!checkUserAllowed(userId, allowedUserIds)) return {
|
|
426
|
-
allowed: false,
|
|
427
|
-
reason: "not-allowlisted"
|
|
428
|
-
};
|
|
429
|
-
return { allowed: true };
|
|
398
|
+
async function authorizeUserForDmWithIngress(params) {
|
|
399
|
+
return await resolveStableChannelMessageIngress({
|
|
400
|
+
channelId: "synology-chat",
|
|
401
|
+
accountId: params.accountId,
|
|
402
|
+
identity: {
|
|
403
|
+
key: "sender-id",
|
|
404
|
+
entryIdPrefix: "synology-chat-entry"
|
|
405
|
+
},
|
|
406
|
+
subject: { stableId: params.userId },
|
|
407
|
+
conversation: {
|
|
408
|
+
kind: "direct",
|
|
409
|
+
id: "direct"
|
|
410
|
+
},
|
|
411
|
+
event: { mayPair: false },
|
|
412
|
+
dmPolicy: params.dmPolicy,
|
|
413
|
+
allowFrom: params.allowedUserIds
|
|
414
|
+
});
|
|
430
415
|
}
|
|
431
416
|
/**
|
|
432
417
|
* Sanitize user input to prevent prompt injection attacks.
|
|
@@ -476,9 +461,6 @@ var RateLimiter = class {
|
|
|
476
461
|
};
|
|
477
462
|
//#endregion
|
|
478
463
|
//#region extensions/synology-chat/src/webhook-handler.ts
|
|
479
|
-
function normalizeLowercaseStringOrEmpty$1(value) {
|
|
480
|
-
return typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
481
|
-
}
|
|
482
464
|
const rateLimiters = /* @__PURE__ */ new Map();
|
|
483
465
|
const invalidTokenRateLimiters = /* @__PURE__ */ new Map();
|
|
484
466
|
const webhookInFlightLimiter = createWebhookInFlightLimiter();
|
|
@@ -642,7 +624,7 @@ function extractTokenFromHeaders(req) {
|
|
|
642
624
|
* - text <- text | message | content
|
|
643
625
|
*/
|
|
644
626
|
function parsePayload(req, body) {
|
|
645
|
-
const contentType = normalizeLowercaseStringOrEmpty
|
|
627
|
+
const contentType = normalizeLowercaseStringOrEmpty(req.headers["content-type"]);
|
|
646
628
|
let bodyFields = {};
|
|
647
629
|
if (contentType.includes("application/json")) bodyFields = parseJsonBody(body);
|
|
648
630
|
else if (contentType.includes("application/x-www-form-urlencoded")) bodyFields = parseFormBody(body);
|
|
@@ -727,7 +709,7 @@ async function parseWebhookPayloadRequest(params) {
|
|
|
727
709
|
payload
|
|
728
710
|
};
|
|
729
711
|
}
|
|
730
|
-
function authorizeSynologyWebhook(params) {
|
|
712
|
+
async function authorizeSynologyWebhook(params) {
|
|
731
713
|
const invalidTokenRateLimitKey = getSynologyWebhookInvalidTokenRateLimitKey(params.req);
|
|
732
714
|
if (params.invalidTokenRateLimiter.isLocked(invalidTokenRateLimitKey)) {
|
|
733
715
|
params.log?.warn(`Rate limit exceeded for remote IP: ${invalidTokenRateLimitKey}`);
|
|
@@ -753,14 +735,19 @@ function authorizeSynologyWebhook(params) {
|
|
|
753
735
|
error: "Invalid token"
|
|
754
736
|
};
|
|
755
737
|
}
|
|
756
|
-
const auth =
|
|
757
|
-
|
|
758
|
-
|
|
738
|
+
const auth = await authorizeUserForDmWithIngress({
|
|
739
|
+
accountId: params.account.accountId,
|
|
740
|
+
userId: params.payload.user_id,
|
|
741
|
+
dmPolicy: params.account.dmPolicy,
|
|
742
|
+
allowedUserIds: params.account.allowedUserIds
|
|
743
|
+
});
|
|
744
|
+
if (!auth.senderAccess.allowed) {
|
|
745
|
+
if (auth.senderAccess.reasonCode === "dm_policy_disabled") return {
|
|
759
746
|
ok: false,
|
|
760
747
|
statusCode: 403,
|
|
761
748
|
error: "DMs are disabled"
|
|
762
749
|
};
|
|
763
|
-
if (
|
|
750
|
+
if (params.account.dmPolicy === "allowlist" && params.account.allowedUserIds.length === 0) {
|
|
764
751
|
params.log?.warn("Synology Chat allowlist is empty while dmPolicy=allowlist; rejecting message");
|
|
765
752
|
return {
|
|
766
753
|
ok: false,
|
|
@@ -785,7 +772,7 @@ function authorizeSynologyWebhook(params) {
|
|
|
785
772
|
}
|
|
786
773
|
return {
|
|
787
774
|
ok: true,
|
|
788
|
-
commandAuthorized: auth.allowed
|
|
775
|
+
commandAuthorized: auth.senderAccess.allowed
|
|
789
776
|
};
|
|
790
777
|
}
|
|
791
778
|
function sanitizeSynologyWebhookText(payload) {
|
|
@@ -796,7 +783,7 @@ function sanitizeSynologyWebhookText(payload) {
|
|
|
796
783
|
async function parseAndAuthorizeSynologyWebhook(params) {
|
|
797
784
|
const parsed = await parseWebhookPayloadRequest(params);
|
|
798
785
|
if (!parsed.ok) return { ok: false };
|
|
799
|
-
const authorized = authorizeSynologyWebhook({
|
|
786
|
+
const authorized = await authorizeSynologyWebhook({
|
|
800
787
|
req: params.req,
|
|
801
788
|
account: params.account,
|
|
802
789
|
payload: parsed.payload,
|
|
@@ -1016,9 +1003,6 @@ function registerSynologyWebhookRoute(params) {
|
|
|
1016
1003
|
* Implements the ChannelPlugin interface following the LINE pattern.
|
|
1017
1004
|
*/
|
|
1018
1005
|
const CHANNEL_ID = "synology-chat";
|
|
1019
|
-
function normalizeLowercaseStringOrEmpty(value) {
|
|
1020
|
-
return typeof value === "string" ? value.trim().toLowerCase() : "";
|
|
1021
|
-
}
|
|
1022
1006
|
const resolveSynologyChatDmPolicy = createScopedDmSecurityResolver({
|
|
1023
1007
|
channelKey: CHANNEL_ID,
|
|
1024
1008
|
resolvePolicy: (account) => account.dmPolicy,
|
|
@@ -1061,6 +1045,53 @@ function requireIncomingUrl(account) {
|
|
|
1061
1045
|
if (!account.incomingUrl) throw new Error("Synology Chat incoming URL not configured");
|
|
1062
1046
|
return account.incomingUrl;
|
|
1063
1047
|
}
|
|
1048
|
+
function createSynologyChatSendResult(params) {
|
|
1049
|
+
return {
|
|
1050
|
+
channel: CHANNEL_ID,
|
|
1051
|
+
messageId: params.messageId,
|
|
1052
|
+
chatId: params.chatId,
|
|
1053
|
+
receipt: createMessageReceiptFromOutboundResults({
|
|
1054
|
+
results: [{
|
|
1055
|
+
channel: CHANNEL_ID,
|
|
1056
|
+
messageId: params.messageId,
|
|
1057
|
+
chatId: params.chatId,
|
|
1058
|
+
conversationId: params.chatId
|
|
1059
|
+
}],
|
|
1060
|
+
threadId: params.chatId,
|
|
1061
|
+
kind: params.kind
|
|
1062
|
+
})
|
|
1063
|
+
};
|
|
1064
|
+
}
|
|
1065
|
+
async function sendSynologyChatText(ctx) {
|
|
1066
|
+
const account = resolveOutboundAccount(ctx.cfg ?? {}, ctx.accountId);
|
|
1067
|
+
if (!await sendMessage(requireIncomingUrl(account), ctx.text, ctx.to, account.allowInsecureSsl)) throw new Error("Failed to send message to Synology Chat");
|
|
1068
|
+
return createSynologyChatSendResult({
|
|
1069
|
+
messageId: `sc-${Date.now()}`,
|
|
1070
|
+
chatId: ctx.to,
|
|
1071
|
+
kind: "text"
|
|
1072
|
+
});
|
|
1073
|
+
}
|
|
1074
|
+
async function sendSynologyChatMedia(ctx) {
|
|
1075
|
+
const account = resolveOutboundAccount(ctx.cfg ?? {}, ctx.accountId);
|
|
1076
|
+
if (!await sendFileUrl(requireIncomingUrl(account), ctx.mediaUrl, ctx.to, account.allowInsecureSsl)) throw new Error("Failed to send media to Synology Chat");
|
|
1077
|
+
return createSynologyChatSendResult({
|
|
1078
|
+
messageId: `sc-${Date.now()}`,
|
|
1079
|
+
chatId: ctx.to,
|
|
1080
|
+
kind: "media"
|
|
1081
|
+
});
|
|
1082
|
+
}
|
|
1083
|
+
const synologyChatMessageAdapter = defineChannelMessageAdapter({
|
|
1084
|
+
id: CHANNEL_ID,
|
|
1085
|
+
durableFinal: { capabilities: {
|
|
1086
|
+
text: true,
|
|
1087
|
+
media: true,
|
|
1088
|
+
messageSendingHooks: true
|
|
1089
|
+
} },
|
|
1090
|
+
send: {
|
|
1091
|
+
text: async (ctx) => await sendSynologyChatText(ctx),
|
|
1092
|
+
media: async (ctx) => await sendSynologyChatMedia(ctx)
|
|
1093
|
+
}
|
|
1094
|
+
});
|
|
1064
1095
|
function createSynologyChatPlugin() {
|
|
1065
1096
|
return createChatChannelPlugin({
|
|
1066
1097
|
base: {
|
|
@@ -1160,7 +1191,8 @@ function createSynologyChatPlugin() {
|
|
|
1160
1191
|
"- Use line breaks to separate sections",
|
|
1161
1192
|
"- Use numbered or bulleted lists for clarity",
|
|
1162
1193
|
"- Wrap URLs with `<URL|label>` for user-friendly links"
|
|
1163
|
-
] }
|
|
1194
|
+
] },
|
|
1195
|
+
message: synologyChatMessageAdapter
|
|
1164
1196
|
},
|
|
1165
1197
|
pairing: { text: {
|
|
1166
1198
|
idLabel: "synologyChatUserId",
|
|
@@ -1180,22 +1212,12 @@ function createSynologyChatPlugin() {
|
|
|
1180
1212
|
outbound: {
|
|
1181
1213
|
deliveryMode: "gateway",
|
|
1182
1214
|
textChunkLimit: 2e3,
|
|
1183
|
-
sendText:
|
|
1184
|
-
|
|
1185
|
-
if (!
|
|
1186
|
-
return
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
});
|
|
1190
|
-
},
|
|
1191
|
-
sendMedia: async ({ to, mediaUrl, accountId, cfg }) => {
|
|
1192
|
-
const account = resolveOutboundAccount(cfg ?? {}, accountId);
|
|
1193
|
-
const incomingUrl = requireIncomingUrl(account);
|
|
1194
|
-
if (!mediaUrl) throw new Error("No media URL provided");
|
|
1195
|
-
if (!await sendFileUrl(incomingUrl, mediaUrl, to, account.allowInsecureSsl)) throw new Error("Failed to send media to Synology Chat");
|
|
1196
|
-
return attachChannelToResult(CHANNEL_ID, {
|
|
1197
|
-
messageId: `sc-${Date.now()}`,
|
|
1198
|
-
chatId: to
|
|
1215
|
+
sendText: sendSynologyChatText,
|
|
1216
|
+
sendMedia: async (ctx) => {
|
|
1217
|
+
if (!ctx.mediaUrl) throw new Error("Synology Chat media send requires mediaUrl");
|
|
1218
|
+
return await sendSynologyChatMedia({
|
|
1219
|
+
...ctx,
|
|
1220
|
+
mediaUrl: ctx.mediaUrl
|
|
1199
1221
|
});
|
|
1200
1222
|
}
|
|
1201
1223
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as synologyChatPlugin } from "./channel-
|
|
1
|
+
import { t as synologyChatPlugin } from "./channel-IPqYKUxY.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-daP5yN4Y.js";
|
|
2
2
|
export { synologyChatSetupAdapter, synologyChatSetupWizard };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { normalizeOptionalString } from "openclaw/plugin-sdk/text-runtime";
|
|
1
2
|
import { DEFAULT_ACCOUNT_ID, listCombinedAccountIds, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-resolution";
|
|
2
3
|
import { resolveDangerousNameMatchingEnabled } from "openclaw/plugin-sdk/dangerous-name-runtime";
|
|
3
4
|
import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$1, createAllowFromSection, createStandardChannelSetupStatus, formatDocsLink, mergeAllowFromEntries, normalizeAccountId, setSetupChannelEnabled, splitSetupEntries } from "openclaw/plugin-sdk/setup";
|
|
@@ -114,10 +115,6 @@ const SYNOLOGY_ALLOW_FROM_HELP_LINES = [
|
|
|
114
115
|
"Multiple entries: comma-separated.",
|
|
115
116
|
`Docs: ${formatDocsLink("/channels/synology-chat", "channels/synology-chat")}`
|
|
116
117
|
];
|
|
117
|
-
function normalizeOptionalString(value) {
|
|
118
|
-
if (typeof value !== "string") return;
|
|
119
|
-
return value.trim() || void 0;
|
|
120
|
-
}
|
|
121
118
|
function getChannelConfig(cfg) {
|
|
122
119
|
return cfg.channels?.[channel] ?? {};
|
|
123
120
|
}
|
package/package.json
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openclaw/synology-chat",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.10-beta.1",
|
|
4
4
|
"description": "Synology Chat channel plugin for OpenClaw",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
7
7
|
"url": "https://github.com/openclaw/openclaw"
|
|
8
8
|
},
|
|
9
9
|
"type": "module",
|
|
10
|
-
"dependencies": {
|
|
11
|
-
"zod": "^4.4.3"
|
|
12
|
-
},
|
|
13
10
|
"devDependencies": {
|
|
14
11
|
"@openclaw/plugin-sdk": "workspace:*"
|
|
15
12
|
},
|
|
@@ -33,10 +30,10 @@
|
|
|
33
30
|
"minHostVersion": ">=2026.4.10"
|
|
34
31
|
},
|
|
35
32
|
"compat": {
|
|
36
|
-
"pluginApi": ">=2026.5.
|
|
33
|
+
"pluginApi": ">=2026.5.10-beta.1"
|
|
37
34
|
},
|
|
38
35
|
"build": {
|
|
39
|
-
"openclawVersion": "2026.5.
|
|
36
|
+
"openclawVersion": "2026.5.10-beta.1"
|
|
40
37
|
},
|
|
41
38
|
"release": {
|
|
42
39
|
"publishToClawHub": true,
|
|
@@ -52,7 +49,7 @@
|
|
|
52
49
|
"openclaw.plugin.json"
|
|
53
50
|
],
|
|
54
51
|
"peerDependencies": {
|
|
55
|
-
"openclaw": ">=2026.5.
|
|
52
|
+
"openclaw": ">=2026.5.10-beta.1"
|
|
56
53
|
},
|
|
57
54
|
"peerDependenciesMeta": {
|
|
58
55
|
"openclaw": {
|