@openclaw/nextcloud-talk 2026.7.1 → 2026.7.2-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,2 +1,2 @@
1
- import { t as nextcloudTalkPlugin } from "./channel-BMKRTDSP.js";
1
+ import { t as nextcloudTalkPlugin } from "./channel-CYse6FwT.js";
2
2
  export { nextcloudTalkPlugin };
@@ -1,26 +1,27 @@
1
1
  import { a as fetchWithSsrFGuard, c as resolveDefaultGroupPolicy, i as deliverFormattedTextWithAttachments, l as warnMissingProviderGroupPolicyFallbackOnce, o as logInboundDrop, r as createChannelPairingController, s as resolveAllowlistProviderRuntimeGroupPolicy, t as GROUP_POLICY_BLOCKED_LABEL, u as getNextcloudTalkRuntime } from "./runtime-api-BKsxTw4J.js";
2
- import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-BY7I5-v9.js";
3
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-CsCJ-vOP.js";
2
+ import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-fNhK1wag.js";
3
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries } from "./secret-contract-DGgvfVqm.js";
4
4
  import { describeWebhookAccountSnapshot } from "openclaw/plugin-sdk/account-helpers";
5
5
  import { createChatChannelPlugin } from "openclaw/plugin-sdk/channel-core";
6
6
  import { createLoggedPairingApprovalNotifier, createPairingPrefixStripper } from "openclaw/plugin-sdk/channel-pairing";
7
- import { createAllowlistProviderRouteAllowlistWarningCollector } from "openclaw/plugin-sdk/channel-policy";
7
+ import { createAllowlistProviderRouteAllowlistWarningCollector, resolveScopeRequireMention, resolveScopeToolsPolicy } from "openclaw/plugin-sdk/channel-policy";
8
8
  import { buildWebhookChannelStatusSummary, createComputedAccountStatusAdapter, createDefaultChannelRuntimeState } from "openclaw/plugin-sdk/status-helpers";
9
+ import { convertMarkdownTables, sanitizeAssistantVisibleText } from "openclaw/plugin-sdk/text-chunking";
10
+ import { createChannelApprovalAuth } from "openclaw/plugin-sdk/approval-auth-runtime";
11
+ import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
9
12
  import { DEFAULT_ACCOUNT_ID, createAccountListHelpers, hasConfiguredAccountValue, normalizeAccountId, resolveAccountWithDefaultFallback, resolveMergedAccountConfig } from "openclaw/plugin-sdk/account-core";
10
13
  import { tryReadSecretFileSync } from "openclaw/plugin-sdk/secret-file-runtime";
11
- import { normalizeLowercaseStringOrEmpty, normalizeOptionalLowercaseString, normalizeOptionalString, normalizeStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
12
14
  import { buildSecretInputSchema, hasConfiguredSecretInput, normalizeResolvedSecretInputString } from "openclaw/plugin-sdk/secret-input";
13
- import { createResolvedApproverActionAuthAdapter, resolveApprovalApprovers } from "openclaw/plugin-sdk/approval-auth-runtime";
14
15
  import { formatErrorMessage } from "openclaw/plugin-sdk/error-runtime";
15
16
  import { parseStrictNonNegativeInteger, parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
16
17
  import { readProviderJsonResponse, readResponseTextLimited } from "openclaw/plugin-sdk/provider-http";
17
- import { createAccountStatusSink, createMessageReceiptFromOutboundResults, defineChannelMessageAdapter } from "openclaw/plugin-sdk/channel-outbound";
18
+ import { createAccountStatusSink, createMessageReceiptFromOutboundResults, defineChannelMessageAdapter, resolveChannelStreamingBlockEnabled } from "openclaw/plugin-sdk/channel-outbound";
18
19
  import { ssrfPolicyFromPrivateNetworkOptIn, ssrfPolicyFromPrivateNetworkOptIn as ssrfPolicyFromPrivateNetworkOptIn$1 } from "openclaw/plugin-sdk/ssrf-runtime";
19
20
  import { readFileSync } from "node:fs";
20
21
  import { requireRuntimeConfig } from "openclaw/plugin-sdk/plugin-config-runtime";
21
22
  import { resolveMarkdownTableMode } from "openclaw/plugin-sdk/markdown-table-runtime";
22
- import { convertMarkdownTables } from "openclaw/plugin-sdk/text-chunking";
23
- import { createHmac, randomBytes, timingSafeEqual } from "node:crypto";
23
+ import { createHmac, randomBytes } from "node:crypto";
24
+ import { safeEqualSecret } from "openclaw/plugin-sdk/security-runtime";
24
25
  import { clearAccountEntryFields } from "openclaw/plugin-sdk/channel-plugin-common";
25
26
  import { DEFAULT_ACCOUNT_ID as DEFAULT_ACCOUNT_ID$2 } from "openclaw/plugin-sdk/account-id";
26
27
  import { DmPolicySchema, GroupPolicySchema, MarkdownConfigSchema, ReplyRuntimeConfigSchemaShape, ToolPolicySchema, buildChannelConfigSchema, requireOpenAllowFrom } from "openclaw/plugin-sdk/channel-config-schema";
@@ -35,8 +36,9 @@ import { createClaimableDedupe, migratePersistentDedupeLegacyJsonFile } from "op
35
36
  import { resolveStateDir } from "openclaw/plugin-sdk/state-paths";
36
37
  import { channelIngressRoutes, resolveStableChannelMessageIngress } from "openclaw/plugin-sdk/channel-ingress-runtime";
37
38
  import { resolveInboundRouteEnvelopeBuilderWithRuntime } from "openclaw/plugin-sdk/inbound-envelope";
38
- import { buildChannelKeyCandidates, normalizeChannelSlug, resolveChannelEntryMatchWithFallback, resolveNestedAllowlistDecision } from "openclaw/plugin-sdk/channel-targets";
39
+ import { buildChannelKeyCandidates, normalizeChannelSlug, resolveChannelEntryMatchWithFallback } from "openclaw/plugin-sdk/channel-targets";
39
40
  import { pruneMapToMaxSize } from "openclaw/plugin-sdk/collection-runtime";
41
+ import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
40
42
  import { createServer } from "node:http";
41
43
  import { WEBHOOK_RATE_LIMIT_DEFAULTS, createAuthRateLimiter, isRequestBodyLimitError, readRequestBodyWithLimit, requestBodyErrorToText } from "openclaw/plugin-sdk/webhook-ingress";
42
44
  import { jsonResult, readStringParam, resolveReactionMessageId } from "openclaw/plugin-sdk/channel-actions";
@@ -139,19 +141,16 @@ function resolveNextcloudTalkAccount(params) {
139
141
  function normalizeNextcloudTalkApproverId(value) {
140
142
  return normalizeOptionalLowercaseString(String(value).trim().replace(/^(nextcloud-talk|nc-talk|nc):/i, ""));
141
143
  }
142
- const nextcloudTalkApprovalAuth = createResolvedApproverActionAuthAdapter({
144
+ const nextcloudTalkApprovalAuth = createChannelApprovalAuth({
143
145
  channelLabel: "Nextcloud Talk",
144
- resolveApprovers: ({ cfg, accountId }) => {
145
- return resolveApprovalApprovers({
146
- allowFrom: resolveNextcloudTalkAccount({
147
- cfg,
148
- accountId
149
- }).config.allowFrom,
150
- normalizeApprover: normalizeNextcloudTalkApproverId
151
- });
146
+ resolveInputs: ({ cfg, accountId }) => {
147
+ return { allowFrom: resolveNextcloudTalkAccount({
148
+ cfg,
149
+ accountId
150
+ }).config.allowFrom };
152
151
  },
153
- normalizeSenderId: (value) => normalizeNextcloudTalkApproverId(value)
154
- });
152
+ normalizeApprover: normalizeNextcloudTalkApproverId
153
+ }).approvalAuth;
155
154
  //#endregion
156
155
  //#region extensions/nextcloud-talk/src/api-credentials.ts
157
156
  function resolveNextcloudTalkApiCredentials(params) {
@@ -188,16 +187,7 @@ const BACKEND_HEADER = "x-nextcloud-talk-backend";
188
187
  function verifyNextcloudTalkSignature(params) {
189
188
  const { signature, random, body, secret } = params;
190
189
  if (!signature || !random || !secret) return false;
191
- const expected = createHmac("sha256", secret).update(random + body).digest("hex");
192
- const expectedBuf = Buffer.from(expected, "utf8");
193
- const signatureBuf = Buffer.from(signature, "utf8");
194
- const maxLen = Math.max(expectedBuf.length, signatureBuf.length);
195
- const paddedExpected = Buffer.alloc(maxLen);
196
- const paddedSignature = Buffer.alloc(maxLen);
197
- expectedBuf.copy(paddedExpected);
198
- signatureBuf.copy(paddedSignature);
199
- const timingResult = timingSafeEqual(paddedExpected, paddedSignature);
200
- return expectedBuf.length === signatureBuf.length && timingResult;
190
+ return safeEqualSecret(signature, createHmac("sha256", secret).update(random + body).digest("hex"));
201
191
  }
202
192
  /**
203
193
  * Extract webhook headers from an incoming request.
@@ -592,12 +582,11 @@ function resolveNextcloudTalkAllowlistMatch(params) {
592
582
  matchSource: "wildcard"
593
583
  };
594
584
  const senderId = normalizeNextcloudTalkAllowEntry(params.senderId);
595
- if (allowFrom.includes(senderId)) return {
585
+ return allowFrom.includes(senderId) ? {
596
586
  allowed: true,
597
587
  matchKey: senderId,
598
588
  matchSource: "id"
599
- };
600
- return { allowed: false };
589
+ } : { allowed: false };
601
590
  }
602
591
  function resolveNextcloudTalkRoomMatch(params) {
603
592
  const rooms = params.rooms ?? {};
@@ -609,12 +598,7 @@ function resolveNextcloudTalkRoomMatch(params) {
609
598
  normalizeKey: normalizeChannelSlug
610
599
  });
611
600
  const roomConfig = match.entry;
612
- const allowed = resolveNestedAllowlistDecision({
613
- outerConfigured: allowlistConfigured,
614
- outerMatched: Boolean(roomConfig),
615
- innerConfigured: false,
616
- innerMatched: false
617
- });
601
+ const allowed = !allowlistConfigured || Boolean(roomConfig);
618
602
  return {
619
603
  roomConfig,
620
604
  wildcardConfig: match.wildcardEntry,
@@ -625,25 +609,52 @@ function resolveNextcloudTalkRoomMatch(params) {
625
609
  };
626
610
  }
627
611
  function resolveNextcloudTalkGroupToolPolicy(params) {
628
- const cfg = params.cfg;
629
612
  const roomToken = params.groupId?.trim();
630
613
  if (!roomToken) return;
631
- const match = resolveNextcloudTalkRoomMatch({
632
- rooms: cfg.channels?.["nextcloud-talk"]?.rooms,
633
- roomToken
614
+ const { tree, toolsPath } = buildNextcloudTalkRoomScope(resolveNextcloudTalkAccount({
615
+ cfg: params.cfg,
616
+ accountId: params.accountId
617
+ }).config.rooms, roomToken);
618
+ return resolveScopeToolsPolicy({
619
+ tree,
620
+ path: toolsPath
634
621
  });
635
- return match.roomConfig?.tools ?? match.wildcardConfig?.tools;
636
622
  }
637
- function resolveNextcloudTalkRequireMention(params) {
638
- if (typeof params.roomConfig?.requireMention === "boolean") return params.roomConfig.requireMention;
639
- if (typeof params.wildcardConfig?.requireMention === "boolean") return params.wildcardConfig.requireMention;
640
- return true;
623
+ function buildNextcloudTalkRoomScope(rooms, roomToken) {
624
+ const { "*": defaults, ...scopes } = rooms ?? {};
625
+ const tree = {
626
+ defaults,
627
+ scopes
628
+ };
629
+ const exactPath = Object.hasOwn(scopes, roomToken) ? [roomToken] : [];
630
+ const toolsMatch = resolveChannelEntryMatchWithFallback({
631
+ entries: scopes,
632
+ keys: buildChannelKeyCandidates(roomToken),
633
+ normalizeKey: normalizeChannelSlug
634
+ });
635
+ return {
636
+ tree,
637
+ exactPath,
638
+ toolsPath: toolsMatch.matchKey ? [toolsMatch.matchKey] : []
639
+ };
640
+ }
641
+ function resolveNextcloudTalkGroupRequireMention(params) {
642
+ if (!params.groupId) return true;
643
+ const { tree, exactPath } = buildNextcloudTalkRoomScope(resolveNextcloudTalkAccount({
644
+ cfg: params.cfg,
645
+ accountId: params.accountId
646
+ }).config.rooms, params.groupId);
647
+ return resolveScopeRequireMention({
648
+ tree,
649
+ path: exactPath
650
+ });
641
651
  }
642
652
  //#endregion
643
653
  //#region extensions/nextcloud-talk/src/room-info.ts
644
654
  const ROOM_CACHE_TTL_MS = 300 * 1e3;
645
655
  const ROOM_CACHE_ERROR_TTL_MS = 30 * 1e3;
646
656
  const ROOM_CACHE_MAX_ENTRIES = 1e3;
657
+ const NEXTCLOUD_TALK_ROOM_INFO_TIMEOUT_MS = 3e4;
647
658
  const roomCache = /* @__PURE__ */ new Map();
648
659
  function resolveRoomCacheKey(params) {
649
660
  return `${params.accountId}:${params.roomToken}`;
@@ -695,7 +706,8 @@ async function resolveNextcloudTalkRoomKind(params) {
695
706
  }
696
707
  },
697
708
  auditContext: "nextcloud-talk.room-info",
698
- policy: ssrfPolicyFromPrivateNetworkOptIn(account.config)
709
+ policy: ssrfPolicyFromPrivateNetworkOptIn(account.config),
710
+ timeoutMs: params.timeoutMs ?? NEXTCLOUD_TALK_ROOM_INFO_TIMEOUT_MS
699
711
  });
700
712
  try {
701
713
  if (!response.ok) {
@@ -730,10 +742,10 @@ function stripNextcloudTalkTargetPrefix(raw) {
730
742
  const trimmed = raw.trim();
731
743
  if (!trimmed) return;
732
744
  let normalized = trimmed;
733
- if (normalized.startsWith("nextcloud-talk:")) normalized = normalized.slice(15).trim();
734
- else if (normalized.startsWith("nc-talk:")) normalized = normalized.slice(8).trim();
735
- else if (normalized.startsWith("nc:")) normalized = normalized.slice(3).trim();
736
- if (normalized.startsWith("room:")) normalized = normalized.slice(5).trim();
745
+ if (/^nextcloud-talk:/i.test(normalized)) normalized = normalized.slice(15).trim();
746
+ else if (/^nc-talk:/i.test(normalized)) normalized = normalized.slice(8).trim();
747
+ else if (/^nc:/i.test(normalized)) normalized = normalized.slice(3).trim();
748
+ if (/^room:/i.test(normalized)) normalized = normalized.slice(5).trim();
737
749
  if (!normalized) return;
738
750
  return normalized;
739
751
  }
@@ -744,17 +756,18 @@ function normalizeNextcloudTalkMessagingTarget(raw) {
744
756
  function looksLikeNextcloudTalkTargetId(raw) {
745
757
  const trimmed = raw.trim();
746
758
  if (!trimmed) return false;
747
- if (/^(nextcloud-talk|nc-talk|nc):/i.test(trimmed)) return true;
759
+ if (/^(nextcloud-talk|nc-talk|nc|room):/i.test(trimmed)) return true;
748
760
  return /^[a-z0-9]{8,}$/i.test(trimmed);
749
761
  }
750
762
  //#endregion
751
763
  //#region extensions/nextcloud-talk/src/send.ts
752
764
  const NEXTCLOUD_TALK_ERROR_SNIPPET_MAX_BYTES = 8 * 1024;
753
765
  const NEXTCLOUD_TALK_ERROR_SNIPPET_MAX_CHARS = 200;
766
+ const NEXTCLOUD_TALK_SEND_TIMEOUT_MS = 3e4;
754
767
  /** Collapses whitespace and caps an error-body prefix to a short, log-safe snippet. */
755
768
  function collapseErrorSnippet(text) {
756
769
  const collapsed = text.replace(/\s+/g, " ").trim();
757
- if (collapsed.length > NEXTCLOUD_TALK_ERROR_SNIPPET_MAX_CHARS) return `${collapsed.slice(0, NEXTCLOUD_TALK_ERROR_SNIPPET_MAX_CHARS)}…`;
770
+ if (collapsed.length > NEXTCLOUD_TALK_ERROR_SNIPPET_MAX_CHARS) return `${truncateUtf16Safe(collapsed, NEXTCLOUD_TALK_ERROR_SNIPPET_MAX_CHARS)}…`;
758
771
  return collapsed;
759
772
  }
760
773
  /** Reads a bounded, collapsed error-body snippet without buffering hostile responses. */
@@ -850,7 +863,8 @@ async function sendMessageNextcloudTalk(to, text, opts) {
850
863
  body: bodyStr
851
864
  },
852
865
  auditContext: "nextcloud-talk-send",
853
- policy: ssrfPolicyFromPrivateNetworkOptIn$1(account.config)
866
+ policy: ssrfPolicyFromPrivateNetworkOptIn$1(account.config),
867
+ timeoutMs: opts.timeoutMs ?? NEXTCLOUD_TALK_SEND_TIMEOUT_MS
854
868
  });
855
869
  try {
856
870
  if (!response.ok) {
@@ -908,7 +922,8 @@ async function sendReactionNextcloudTalk(roomToken, messageId, reaction, opts) {
908
922
  body
909
923
  },
910
924
  auditContext: "nextcloud-talk-reaction",
911
- policy: ssrfPolicyFromPrivateNetworkOptIn$1(account.config)
925
+ policy: ssrfPolicyFromPrivateNetworkOptIn$1(account.config),
926
+ timeoutMs: opts.timeoutMs ?? NEXTCLOUD_TALK_SEND_TIMEOUT_MS
912
927
  });
913
928
  try {
914
929
  if (!response.ok) {
@@ -959,7 +974,7 @@ function roomRoutes(params) {
959
974
  }
960
975
  async function deliverNextcloudTalkReply(params) {
961
976
  const { cfg, payload, roomToken, accountId, statusSink } = params;
962
- await deliverFormattedTextWithAttachments({
977
+ return { visibleReplySent: await deliverFormattedTextWithAttachments({
963
978
  payload,
964
979
  send: async ({ text, replyToId }) => {
965
980
  await sendMessageNextcloudTalk(roomToken, text, {
@@ -969,7 +984,7 @@ async function deliverNextcloudTalkReply(params) {
969
984
  });
970
985
  statusSink?.({ lastOutboundAt: Date.now() });
971
986
  }
972
- });
987
+ }) };
973
988
  }
974
989
  async function handleNextcloudTalkInbound(params) {
975
990
  const { message, account, config, runtime, statusSink } = params;
@@ -1002,9 +1017,10 @@ async function handleNextcloudTalkInbound(params) {
1002
1017
  surface: CHANNEL_ID
1003
1018
  });
1004
1019
  const hasControlCommand = core.channel.text.hasControlCommand(rawBody, config);
1005
- const shouldRequireMention = isGroup ? resolveNextcloudTalkRequireMention({
1006
- roomConfig,
1007
- wildcardConfig: roomMatch.wildcardConfig
1020
+ const shouldRequireMention = isGroup ? resolveNextcloudTalkGroupRequireMention({
1021
+ cfg: config,
1022
+ accountId: account.accountId,
1023
+ groupId: roomToken
1008
1024
  }) : false;
1009
1025
  const { groupPolicy, providerMissingFallbackApplied } = resolveAllowlistProviderRuntimeGroupPolicy({
1010
1026
  providerConfigPresent: (config.channels?.[CHANNEL_ID] ?? void 0) !== void 0,
@@ -1141,6 +1157,7 @@ async function handleNextcloudTalkInbound(params) {
1141
1157
  body: rawBody
1142
1158
  });
1143
1159
  const groupSystemPrompt = normalizeOptionalString(roomConfig?.systemPrompt);
1160
+ const blockStreamingEnabled = resolveChannelStreamingBlockEnabled(account.config);
1144
1161
  const ctxPayload = core.channel.reply.finalizeInboundContext({
1145
1162
  Body: body,
1146
1163
  BodyForAgent: rawBody,
@@ -1176,8 +1193,12 @@ async function handleNextcloudTalkInbound(params) {
1176
1193
  recordInboundSession: core.channel.session.recordInboundSession,
1177
1194
  dispatchReplyWithBufferedBlockDispatcher: core.channel.reply.dispatchReplyWithBufferedBlockDispatcher,
1178
1195
  delivery: {
1196
+ preparePayload: (payload) => payload.text === void 0 ? payload : {
1197
+ ...payload,
1198
+ text: sanitizeAssistantVisibleText(payload.text)
1199
+ },
1179
1200
  deliver: async (payload) => {
1180
- await deliverNextcloudTalkReply({
1201
+ return await deliverNextcloudTalkReply({
1181
1202
  cfg: config,
1182
1203
  payload,
1183
1204
  roomToken,
@@ -1192,7 +1213,7 @@ async function handleNextcloudTalkInbound(params) {
1192
1213
  replyPipeline: {},
1193
1214
  replyOptions: {
1194
1215
  skillFilter: roomConfig?.skills,
1195
- disableBlockStreaming: typeof account.config.blockStreaming === "boolean" ? !account.config.blockStreaming : void 0
1216
+ disableBlockStreaming: typeof blockStreamingEnabled === "boolean" ? !blockStreamingEnabled : void 0
1196
1217
  },
1197
1218
  record: { onRecordError: (err) => {
1198
1219
  runtime.error?.(`nextcloud-talk: failed updating session meta: ${String(err)}`);
@@ -1651,7 +1672,7 @@ const nextcloudTalkMessageActions = {
1651
1672
  if (!hasConfiguredAccount(cfg, accountId)) return null;
1652
1673
  return { actions: ["send", "react"] };
1653
1674
  },
1654
- supportsAction: ({ action }) => action !== "send",
1675
+ supportsAction: ({ action }) => action === "react",
1655
1676
  handleAction: async ({ action, params, cfg, accountId, toolContext }) => {
1656
1677
  if (action === "send") throw new Error("Send should be handled by outbound, not actions handler.");
1657
1678
  if (action === "react") {
@@ -2076,18 +2097,7 @@ const nextcloudTalkPlugin = createChatChannelPlugin({
2076
2097
  approvalCapability: nextcloudTalkApprovalAuth,
2077
2098
  doctor: nextcloudTalkDoctor,
2078
2099
  groups: {
2079
- resolveRequireMention: ({ cfg, accountId, groupId }) => {
2080
- const rooms = resolveNextcloudTalkAccount({
2081
- cfg,
2082
- accountId
2083
- }).config.rooms;
2084
- if (!rooms || !groupId) return true;
2085
- const roomConfig = rooms[groupId];
2086
- if (roomConfig?.requireMention !== void 0) return roomConfig.requireMention;
2087
- const wildcardConfig = rooms["*"];
2088
- if (wildcardConfig?.requireMention !== void 0) return wildcardConfig.requireMention;
2089
- return true;
2090
- },
2100
+ resolveRequireMention: resolveNextcloudTalkGroupRequireMention,
2091
2101
  resolveToolPolicy: resolveNextcloudTalkGroupToolPolicy
2092
2102
  },
2093
2103
  messaging: {
@@ -2155,7 +2165,8 @@ const nextcloudTalkPlugin = createChatChannelPlugin({
2155
2165
  deliveryMode: "direct",
2156
2166
  chunker: (text, limit) => getNextcloudTalkRuntime().channel.text.chunkMarkdownText(text, limit),
2157
2167
  chunkerMode: "markdown",
2158
- textChunkLimit: 4e3
2168
+ textChunkLimit: 4e3,
2169
+ sanitizeText: ({ text }) => sanitizeAssistantVisibleText(text)
2159
2170
  },
2160
2171
  attachedResults: {
2161
2172
  channel: "nextcloud-talk",
@@ -1,2 +1,2 @@
1
- import { t as nextcloudTalkPlugin } from "./channel-BMKRTDSP.js";
1
+ import { t as nextcloudTalkPlugin } from "./channel-CYse6FwT.js";
2
2
  export { nextcloudTalkPlugin };
@@ -1,2 +1,2 @@
1
- import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-BY7I5-v9.js";
1
+ import { n as normalizeCompatibilityConfig, t as legacyConfigRules } from "./doctor-contract-fNhK1wag.js";
2
2
  export { legacyConfigRules, normalizeCompatibilityConfig };
@@ -0,0 +1,22 @@
1
+ import { createLegacyPrivateNetworkDoctorContract } from "openclaw/plugin-sdk/ssrf-runtime";
2
+ import { defineChannelAliasMigration } from "openclaw/plugin-sdk/runtime-doctor";
3
+ //#region extensions/nextcloud-talk/src/doctor-contract.ts
4
+ const networkContract = createLegacyPrivateNetworkDoctorContract({ channelKey: "nextcloud-talk" });
5
+ const streamingAliasMigration = defineChannelAliasMigration({
6
+ channelId: "nextcloud-talk",
7
+ streaming: {
8
+ defaultMode: "partial",
9
+ deliveryOnly: true
10
+ },
11
+ accountStreamingReplacesRoot: true
12
+ });
13
+ const legacyConfigRules = [...networkContract.legacyConfigRules, ...streamingAliasMigration.legacyConfigRules];
14
+ function normalizeCompatibilityConfig({ cfg }) {
15
+ const network = networkContract.normalizeCompatibilityConfig({ cfg });
16
+ return streamingAliasMigration.normalizeChannelConfig({
17
+ cfg: network.config,
18
+ changes: network.changes
19
+ });
20
+ }
21
+ //#endregion
22
+ export { normalizeCompatibilityConfig as n, legacyConfigRules as t };
@@ -1,51 +1,10 @@
1
- import { collectConditionalChannelFieldAssignments, getChannelSurface, hasOwnProperty } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
1
+ import { collectConditionalChannelFieldAssignments, createChannelSecretTargetRegistryEntries, getChannelSurface, hasOwnProperty } from "openclaw/plugin-sdk/channel-secret-basic-runtime";
2
2
  //#region extensions/nextcloud-talk/src/secret-contract.ts
3
- const secretTargetRegistryEntries = [
4
- {
5
- id: "channels.nextcloud-talk.accounts.*.apiPassword",
6
- targetType: "channels.nextcloud-talk.accounts.*.apiPassword",
7
- configFile: "openclaw.json",
8
- pathPattern: "channels.nextcloud-talk.accounts.*.apiPassword",
9
- secretShape: "secret_input",
10
- expectedResolvedValue: "string",
11
- includeInPlan: true,
12
- includeInConfigure: true,
13
- includeInAudit: true
14
- },
15
- {
16
- id: "channels.nextcloud-talk.accounts.*.botSecret",
17
- targetType: "channels.nextcloud-talk.accounts.*.botSecret",
18
- configFile: "openclaw.json",
19
- pathPattern: "channels.nextcloud-talk.accounts.*.botSecret",
20
- secretShape: "secret_input",
21
- expectedResolvedValue: "string",
22
- includeInPlan: true,
23
- includeInConfigure: true,
24
- includeInAudit: true
25
- },
26
- {
27
- id: "channels.nextcloud-talk.apiPassword",
28
- targetType: "channels.nextcloud-talk.apiPassword",
29
- configFile: "openclaw.json",
30
- pathPattern: "channels.nextcloud-talk.apiPassword",
31
- secretShape: "secret_input",
32
- expectedResolvedValue: "string",
33
- includeInPlan: true,
34
- includeInConfigure: true,
35
- includeInAudit: true
36
- },
37
- {
38
- id: "channels.nextcloud-talk.botSecret",
39
- targetType: "channels.nextcloud-talk.botSecret",
40
- configFile: "openclaw.json",
41
- pathPattern: "channels.nextcloud-talk.botSecret",
42
- secretShape: "secret_input",
43
- expectedResolvedValue: "string",
44
- includeInPlan: true,
45
- includeInConfigure: true,
46
- includeInAudit: true
47
- }
48
- ];
3
+ const secretTargetRegistryEntries = createChannelSecretTargetRegistryEntries({
4
+ channelKey: "nextcloud-talk",
5
+ account: ["apiPassword", "botSecret"],
6
+ channel: ["apiPassword", "botSecret"]
7
+ });
49
8
  function collectRuntimeConfigAssignments(params) {
50
9
  const resolved = getChannelSurface(params.config, "nextcloud-talk");
51
10
  if (!resolved) return;
@@ -1,2 +1,2 @@
1
- import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-CsCJ-vOP.js";
1
+ import { n as collectRuntimeConfigAssignments, r as secretTargetRegistryEntries, t as channelSecrets } from "./secret-contract-DGgvfVqm.js";
2
2
  export { channelSecrets, collectRuntimeConfigAssignments, secretTargetRegistryEntries };
@@ -1,17 +1,17 @@
1
1
  {
2
2
  "name": "@openclaw/nextcloud-talk",
3
- "version": "2026.7.1",
3
+ "version": "2026.7.2-beta.1",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@openclaw/nextcloud-talk",
9
- "version": "2026.7.1",
9
+ "version": "2026.7.2-beta.1",
10
10
  "dependencies": {
11
11
  "zod": "4.4.3"
12
12
  },
13
13
  "peerDependencies": {
14
- "openclaw": ">=2026.7.1"
14
+ "openclaw": ">=2026.7.2-beta.1"
15
15
  },
16
16
  "peerDependenciesMeta": {
17
17
  "openclaw": {
@@ -366,33 +366,45 @@
366
366
  "exclusiveMinimum": 0,
367
367
  "maximum": 9007199254740991
368
368
  },
369
- "chunkMode": {
370
- "type": "string",
371
- "enum": [
372
- "length",
373
- "newline"
374
- ]
375
- },
376
- "blockStreaming": {
377
- "type": "boolean"
378
- },
379
- "blockStreamingCoalesce": {
369
+ "streaming": {
380
370
  "type": "object",
381
371
  "properties": {
382
- "minChars": {
383
- "type": "integer",
384
- "exclusiveMinimum": 0,
385
- "maximum": 9007199254740991
386
- },
387
- "maxChars": {
388
- "type": "integer",
389
- "exclusiveMinimum": 0,
390
- "maximum": 9007199254740991
372
+ "chunkMode": {
373
+ "type": "string",
374
+ "enum": [
375
+ "length",
376
+ "newline"
377
+ ]
391
378
  },
392
- "idleMs": {
393
- "type": "integer",
394
- "minimum": 0,
395
- "maximum": 9007199254740991
379
+ "block": {
380
+ "type": "object",
381
+ "properties": {
382
+ "enabled": {
383
+ "type": "boolean"
384
+ },
385
+ "coalesce": {
386
+ "type": "object",
387
+ "properties": {
388
+ "minChars": {
389
+ "type": "integer",
390
+ "exclusiveMinimum": 0,
391
+ "maximum": 9007199254740991
392
+ },
393
+ "maxChars": {
394
+ "type": "integer",
395
+ "exclusiveMinimum": 0,
396
+ "maximum": 9007199254740991
397
+ },
398
+ "idleMs": {
399
+ "type": "integer",
400
+ "minimum": 0,
401
+ "maximum": 9007199254740991
402
+ }
403
+ },
404
+ "additionalProperties": false
405
+ }
406
+ },
407
+ "additionalProperties": false
396
408
  }
397
409
  },
398
410
  "additionalProperties": false
@@ -752,33 +764,45 @@
752
764
  "exclusiveMinimum": 0,
753
765
  "maximum": 9007199254740991
754
766
  },
755
- "chunkMode": {
756
- "type": "string",
757
- "enum": [
758
- "length",
759
- "newline"
760
- ]
761
- },
762
- "blockStreaming": {
763
- "type": "boolean"
764
- },
765
- "blockStreamingCoalesce": {
767
+ "streaming": {
766
768
  "type": "object",
767
769
  "properties": {
768
- "minChars": {
769
- "type": "integer",
770
- "exclusiveMinimum": 0,
771
- "maximum": 9007199254740991
772
- },
773
- "maxChars": {
774
- "type": "integer",
775
- "exclusiveMinimum": 0,
776
- "maximum": 9007199254740991
770
+ "chunkMode": {
771
+ "type": "string",
772
+ "enum": [
773
+ "length",
774
+ "newline"
775
+ ]
777
776
  },
778
- "idleMs": {
779
- "type": "integer",
780
- "minimum": 0,
781
- "maximum": 9007199254740991
777
+ "block": {
778
+ "type": "object",
779
+ "properties": {
780
+ "enabled": {
781
+ "type": "boolean"
782
+ },
783
+ "coalesce": {
784
+ "type": "object",
785
+ "properties": {
786
+ "minChars": {
787
+ "type": "integer",
788
+ "exclusiveMinimum": 0,
789
+ "maximum": 9007199254740991
790
+ },
791
+ "maxChars": {
792
+ "type": "integer",
793
+ "exclusiveMinimum": 0,
794
+ "maximum": 9007199254740991
795
+ },
796
+ "idleMs": {
797
+ "type": "integer",
798
+ "minimum": 0,
799
+ "maximum": 9007199254740991
800
+ }
801
+ },
802
+ "additionalProperties": false
803
+ }
804
+ },
805
+ "additionalProperties": false
782
806
  }
783
807
  },
784
808
  "additionalProperties": false
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/nextcloud-talk",
3
- "version": "2026.7.1",
3
+ "version": "2026.7.2-beta.1",
4
4
  "description": "OpenClaw Nextcloud Talk channel plugin for conversations.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -8,7 +8,7 @@
8
8
  },
9
9
  "type": "module",
10
10
  "peerDependencies": {
11
- "openclaw": ">=2026.7.1"
11
+ "openclaw": ">=2026.7.2-beta.1"
12
12
  },
13
13
  "peerDependenciesMeta": {
14
14
  "openclaw": {
@@ -40,10 +40,10 @@
40
40
  "minHostVersion": ">=2026.4.10"
41
41
  },
42
42
  "compat": {
43
- "pluginApi": ">=2026.7.1"
43
+ "pluginApi": ">=2026.7.2-beta.1"
44
44
  },
45
45
  "build": {
46
- "openclawVersion": "2026.7.1"
46
+ "openclawVersion": "2026.7.2-beta.1"
47
47
  },
48
48
  "release": {
49
49
  "publishToClawHub": true,
@@ -1,7 +0,0 @@
1
- import { createLegacyPrivateNetworkDoctorContract } from "openclaw/plugin-sdk/ssrf-runtime";
2
- //#region extensions/nextcloud-talk/src/doctor-contract.ts
3
- const contract = createLegacyPrivateNetworkDoctorContract({ channelKey: "nextcloud-talk" });
4
- const legacyConfigRules = contract.legacyConfigRules;
5
- const normalizeCompatibilityConfig = contract.normalizeCompatibilityConfig;
6
- //#endregion
7
- export { normalizeCompatibilityConfig as n, legacyConfigRules as t };