@openclaw/nextcloud-talk 2026.2.22 → 2026.2.24

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/package.json CHANGED
@@ -1,11 +1,8 @@
1
1
  {
2
2
  "name": "@openclaw/nextcloud-talk",
3
- "version": "2026.2.22",
3
+ "version": "2026.2.24",
4
4
  "description": "OpenClaw Nextcloud Talk channel plugin",
5
5
  "type": "module",
6
- "devDependencies": {
7
- "openclaw": "workspace:*"
8
- },
9
6
  "openclaw": {
10
7
  "extensions": [
11
8
  "./index.ts"
@@ -4,6 +4,7 @@ import {
4
4
  DmPolicySchema,
5
5
  GroupPolicySchema,
6
6
  MarkdownConfigSchema,
7
+ ReplyRuntimeConfigSchemaShape,
7
8
  ToolPolicySchema,
8
9
  requireOpenAllowFrom,
9
10
  } from "openclaw/plugin-sdk";
@@ -40,15 +41,7 @@ export const NextcloudTalkAccountSchemaBase = z
40
41
  groupAllowFrom: z.array(z.string()).optional(),
41
42
  groupPolicy: GroupPolicySchema.optional().default("allowlist"),
42
43
  rooms: z.record(z.string(), NextcloudTalkRoomSchema.optional()).optional(),
43
- historyLimit: z.number().int().min(0).optional(),
44
- dmHistoryLimit: z.number().int().min(0).optional(),
45
- dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
46
- textChunkLimit: z.number().int().positive().optional(),
47
- chunkMode: z.enum(["length", "newline"]).optional(),
48
- blockStreaming: z.boolean().optional(),
49
- blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
50
- responsePrefix: z.string().optional(),
51
- mediaMaxMb: z.number().positive().optional(),
44
+ ...ReplyRuntimeConfigSchemaShape,
52
45
  })
53
46
  .strict();
54
47
 
package/src/inbound.ts CHANGED
@@ -1,11 +1,15 @@
1
1
  import {
2
2
  GROUP_POLICY_BLOCKED_LABEL,
3
+ createNormalizedOutboundDeliverer,
3
4
  createReplyPrefixOptions,
5
+ formatTextWithAttachmentLinks,
4
6
  logInboundDrop,
5
7
  resolveControlCommandGate,
8
+ resolveOutboundMediaUrls,
6
9
  resolveAllowlistProviderRuntimeGroupPolicy,
7
10
  resolveDefaultGroupPolicy,
8
11
  warnMissingProviderGroupPolicyFallbackOnce,
12
+ type OutboundReplyPayload,
9
13
  type OpenClawConfig,
10
14
  type RuntimeEnv,
11
15
  } from "openclaw/plugin-sdk";
@@ -26,32 +30,17 @@ import type { CoreConfig, GroupPolicy, NextcloudTalkInboundMessage } from "./typ
26
30
  const CHANNEL_ID = "nextcloud-talk" as const;
27
31
 
28
32
  async function deliverNextcloudTalkReply(params: {
29
- payload: { text?: string; mediaUrls?: string[]; mediaUrl?: string; replyToId?: string };
33
+ payload: OutboundReplyPayload;
30
34
  roomToken: string;
31
35
  accountId: string;
32
36
  statusSink?: (patch: { lastOutboundAt?: number }) => void;
33
37
  }): Promise<void> {
34
38
  const { payload, roomToken, accountId, statusSink } = params;
35
- const text = payload.text ?? "";
36
- const mediaList = payload.mediaUrls?.length
37
- ? payload.mediaUrls
38
- : payload.mediaUrl
39
- ? [payload.mediaUrl]
40
- : [];
41
-
42
- if (!text.trim() && mediaList.length === 0) {
39
+ const combined = formatTextWithAttachmentLinks(payload.text, resolveOutboundMediaUrls(payload));
40
+ if (!combined) {
43
41
  return;
44
42
  }
45
43
 
46
- const mediaBlock = mediaList.length
47
- ? mediaList.map((url) => `Attachment: ${url}`).join("\n")
48
- : "";
49
- const combined = text.trim()
50
- ? mediaBlock
51
- ? `${text.trim()}\n\n${mediaBlock}`
52
- : text.trim()
53
- : mediaBlock;
54
-
55
44
  await sendMessageNextcloudTalk(roomToken, combined, {
56
45
  accountId,
57
46
  replyTo: payload.replyToId,
@@ -318,25 +307,21 @@ export async function handleNextcloudTalkInbound(params: {
318
307
  channel: CHANNEL_ID,
319
308
  accountId: account.accountId,
320
309
  });
310
+ const deliverReply = createNormalizedOutboundDeliverer(async (payload) => {
311
+ await deliverNextcloudTalkReply({
312
+ payload,
313
+ roomToken,
314
+ accountId: account.accountId,
315
+ statusSink,
316
+ });
317
+ });
321
318
 
322
319
  await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
323
320
  ctx: ctxPayload,
324
321
  cfg: config as OpenClawConfig,
325
322
  dispatcherOptions: {
326
323
  ...prefixOptions,
327
- deliver: async (payload) => {
328
- await deliverNextcloudTalkReply({
329
- payload: payload as {
330
- text?: string;
331
- mediaUrls?: string[];
332
- mediaUrl?: string;
333
- replyToId?: string;
334
- },
335
- roomToken,
336
- accountId: account.accountId,
337
- statusSink,
338
- });
339
- },
324
+ deliver: deliverReply,
340
325
  onError: (err, info) => {
341
326
  runtime.error?.(`nextcloud-talk ${info.kind} reply failed: ${String(err)}`);
342
327
  },
package/src/monitor.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { createServer, type IncomingMessage, type Server, type ServerResponse } from "node:http";
2
2
  import {
3
+ createLoggerBackedRuntime,
3
4
  type RuntimeEnv,
4
5
  isRequestBodyLimitError,
5
6
  readRequestBodyWithLimit,
@@ -212,13 +213,12 @@ export async function monitorNextcloudTalkProvider(
212
213
  cfg,
213
214
  accountId: opts.accountId,
214
215
  });
215
- const runtime: RuntimeEnv = opts.runtime ?? {
216
- log: (...args: unknown[]) => core.logging.getChildLogger().info(args.map(String).join(" ")),
217
- error: (...args: unknown[]) => core.logging.getChildLogger().error(args.map(String).join(" ")),
218
- exit: () => {
219
- throw new Error("Runtime exit not available");
220
- },
221
- };
216
+ const runtime: RuntimeEnv =
217
+ opts.runtime ??
218
+ createLoggerBackedRuntime({
219
+ logger: core.logging.getChildLogger(),
220
+ exitError: () => new Error("Runtime exit not available"),
221
+ });
222
222
 
223
223
  if (!account.secret) {
224
224
  throw new Error(`Nextcloud Talk bot secret not configured for account "${account.accountId}"`);