@clawdbot/zalouser 2026.1.21 → 2026.1.23

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## 2026.1.23
4
+
5
+ ### Changes
6
+ - Version alignment with core Clawdbot release numbers.
7
+
8
+ ## 2026.1.22
9
+
10
+ ### Changes
11
+ - Version alignment with core Clawdbot release numbers.
12
+
3
13
  ## 2026.1.21
4
14
 
5
15
  ### Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@clawdbot/zalouser",
3
- "version": "2026.1.21",
3
+ "version": "2026.1.23",
4
4
  "type": "module",
5
5
  "description": "Clawdbot Zalo Personal Account plugin via zca-cli",
6
6
  "dependencies": {
package/src/channel.ts CHANGED
@@ -2,8 +2,10 @@ import type {
2
2
  ChannelAccountSnapshot,
3
3
  ChannelDirectoryEntry,
4
4
  ChannelDock,
5
+ ChannelGroupContext,
5
6
  ChannelPlugin,
6
7
  ClawdbotConfig,
8
+ GroupToolPolicyConfig,
7
9
  } from "clawdbot/plugin-sdk";
8
10
  import {
9
11
  applyAccountNameToChannelSection,
@@ -79,6 +81,26 @@ function mapGroup(params: {
79
81
  };
80
82
  }
81
83
 
84
+ function resolveZalouserGroupToolPolicy(
85
+ params: ChannelGroupContext,
86
+ ): GroupToolPolicyConfig | undefined {
87
+ const account = resolveZalouserAccountSync({
88
+ cfg: params.cfg as ClawdbotConfig,
89
+ accountId: params.accountId ?? undefined,
90
+ });
91
+ const groups = account.config.groups ?? {};
92
+ const groupId = params.groupId?.trim();
93
+ const groupChannel = params.groupChannel?.trim();
94
+ const candidates = [groupId, groupChannel, "*"].filter(
95
+ (value): value is string => Boolean(value),
96
+ );
97
+ for (const key of candidates) {
98
+ const entry = groups[key];
99
+ if (entry?.tools) return entry.tools;
100
+ }
101
+ return undefined;
102
+ }
103
+
82
104
  export const zalouserDock: ChannelDock = {
83
105
  id: "zalouser",
84
106
  capabilities: {
@@ -101,6 +123,7 @@ export const zalouserDock: ChannelDock = {
101
123
  },
102
124
  groups: {
103
125
  resolveRequireMention: () => true,
126
+ resolveToolPolicy: resolveZalouserGroupToolPolicy,
104
127
  },
105
128
  threading: {
106
129
  resolveReplyToMode: () => "off",
@@ -188,6 +211,7 @@ export const zalouserPlugin: ChannelPlugin<ResolvedZalouserAccount> = {
188
211
  },
189
212
  groups: {
190
213
  resolveRequireMention: () => true,
214
+ resolveToolPolicy: resolveZalouserGroupToolPolicy,
191
215
  },
192
216
  threading: {
193
217
  resolveReplyToMode: () => "off",
@@ -1,3 +1,4 @@
1
+ import { MarkdownConfigSchema, ToolPolicySchema } from "clawdbot/plugin-sdk";
1
2
  import { z } from "zod";
2
3
 
3
4
  const allowFromEntry = z.union([z.string(), z.number()]);
@@ -5,11 +6,13 @@ const allowFromEntry = z.union([z.string(), z.number()]);
5
6
  const groupConfigSchema = z.object({
6
7
  allow: z.boolean().optional(),
7
8
  enabled: z.boolean().optional(),
9
+ tools: ToolPolicySchema,
8
10
  });
9
11
 
10
12
  const zalouserAccountSchema = z.object({
11
13
  name: z.string().optional(),
12
14
  enabled: z.boolean().optional(),
15
+ markdown: MarkdownConfigSchema,
13
16
  profile: z.string().optional(),
14
17
  dmPolicy: z.enum(["pairing", "allowlist", "open", "disabled"]).optional(),
15
18
  allowFrom: z.array(allowFromEntry).optional(),
package/src/monitor.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import type { ChildProcess } from "node:child_process";
2
2
 
3
- import type { ClawdbotConfig, RuntimeEnv } from "clawdbot/plugin-sdk";
3
+ import type { ClawdbotConfig, MarkdownTableMode, RuntimeEnv } from "clawdbot/plugin-sdk";
4
4
  import { mergeAllowlist, summarizeMapping } from "clawdbot/plugin-sdk";
5
5
  import { sendMessageZalouser } from "./send.js";
6
6
  import type {
@@ -311,12 +311,13 @@ async function processMessage(
311
311
  OriginatingTo: `zalouser:${chatId}`,
312
312
  });
313
313
 
314
- void core.channel.session.recordSessionMetaFromInbound({
314
+ await core.channel.session.recordInboundSession({
315
315
  storePath,
316
316
  sessionKey: ctxPayload.SessionKey ?? route.sessionKey,
317
317
  ctx: ctxPayload,
318
- }).catch((err) => {
319
- runtime.error?.(`zalouser: failed updating session meta: ${String(err)}`);
318
+ onRecordError: (err) => {
319
+ runtime.error?.(`zalouser: failed updating session meta: ${String(err)}`);
320
+ },
320
321
  });
321
322
 
322
323
  await core.channel.reply.dispatchReplyWithBufferedBlockDispatcher({
@@ -332,6 +333,11 @@ async function processMessage(
332
333
  runtime,
333
334
  core,
334
335
  statusSink,
336
+ tableMode: core.channel.text.resolveMarkdownTableMode({
337
+ cfg: config,
338
+ channel: "zalouser",
339
+ accountId: account.accountId,
340
+ }),
335
341
  });
336
342
  },
337
343
  onError: (err, info) => {
@@ -351,8 +357,11 @@ async function deliverZalouserReply(params: {
351
357
  runtime: RuntimeEnv;
352
358
  core: ZalouserCoreRuntime;
353
359
  statusSink?: (patch: { lastInboundAt?: number; lastOutboundAt?: number }) => void;
360
+ tableMode?: MarkdownTableMode;
354
361
  }): Promise<void> {
355
362
  const { payload, profile, chatId, isGroup, runtime, core, statusSink } = params;
363
+ const tableMode = params.tableMode ?? "code";
364
+ const text = core.channel.text.convertMarkdownTables(payload.text ?? "", tableMode);
356
365
 
357
366
  const mediaList = payload.mediaUrls?.length
358
367
  ? payload.mediaUrls
@@ -363,7 +372,7 @@ async function deliverZalouserReply(params: {
363
372
  if (mediaList.length > 0) {
364
373
  let first = true;
365
374
  for (const mediaUrl of mediaList) {
366
- const caption = first ? payload.text : undefined;
375
+ const caption = first ? text : undefined;
367
376
  first = false;
368
377
  try {
369
378
  logVerbose(core, runtime, `Sending media to ${chatId}`);
@@ -380,8 +389,8 @@ async function deliverZalouserReply(params: {
380
389
  return;
381
390
  }
382
391
 
383
- if (payload.text) {
384
- const chunks = core.channel.text.chunkMarkdownText(payload.text, ZALOUSER_TEXT_LIMIT);
392
+ if (text) {
393
+ const chunks = core.channel.text.chunkMarkdownText(text, ZALOUSER_TEXT_LIMIT);
385
394
  logVerbose(core, runtime, `Sending ${chunks.length} text chunk(s) to ${chatId}`);
386
395
  for (const chunk of chunks) {
387
396
  try {
package/src/types.ts CHANGED
@@ -75,7 +75,7 @@ export type ZalouserAccountConfig = {
75
75
  dmPolicy?: "pairing" | "allowlist" | "open" | "disabled";
76
76
  allowFrom?: Array<string | number>;
77
77
  groupPolicy?: "open" | "allowlist" | "disabled";
78
- groups?: Record<string, { allow?: boolean; enabled?: boolean }>;
78
+ groups?: Record<string, { allow?: boolean; enabled?: boolean; tools?: { allow?: string[]; deny?: string[] } }>;
79
79
  messagePrefix?: string;
80
80
  };
81
81
 
@@ -87,7 +87,7 @@ export type ZalouserConfig = {
87
87
  dmPolicy?: "pairing" | "allowlist" | "open" | "disabled";
88
88
  allowFrom?: Array<string | number>;
89
89
  groupPolicy?: "open" | "allowlist" | "disabled";
90
- groups?: Record<string, { allow?: boolean; enabled?: boolean }>;
90
+ groups?: Record<string, { allow?: boolean; enabled?: boolean; tools?: { allow?: string[]; deny?: string[] } }>;
91
91
  messagePrefix?: string;
92
92
  accounts?: Record<string, ZalouserAccountConfig>;
93
93
  };