mirror of
https://github.com/openclaw/openclaw.git
synced 2026-02-19 18:39:20 -05:00
refactor(config): share whatsapp zod schemas
This commit is contained in:
@@ -11,137 +11,108 @@ import {
|
||||
|
||||
const ToolPolicyBySenderSchema = z.record(z.string(), ToolPolicySchema).optional();
|
||||
|
||||
export const WhatsAppAccountSchema = z
|
||||
const WhatsAppGroupEntrySchema = z
|
||||
.object({
|
||||
name: z.string().optional(),
|
||||
capabilities: z.array(z.string()).optional(),
|
||||
markdown: MarkdownConfigSchema,
|
||||
configWrites: z.boolean().optional(),
|
||||
enabled: z.boolean().optional(),
|
||||
sendReadReceipts: z.boolean().optional(),
|
||||
messagePrefix: z.string().optional(),
|
||||
responsePrefix: z.string().optional(),
|
||||
/** Override auth directory for this WhatsApp account (Baileys multi-file auth state). */
|
||||
authDir: z.string().optional(),
|
||||
dmPolicy: DmPolicySchema.optional().default("pairing"),
|
||||
selfChatMode: z.boolean().optional(),
|
||||
allowFrom: z.array(z.string()).optional(),
|
||||
groupAllowFrom: z.array(z.string()).optional(),
|
||||
groupPolicy: GroupPolicySchema.optional().default("allowlist"),
|
||||
historyLimit: z.number().int().min(0).optional(),
|
||||
dmHistoryLimit: z.number().int().min(0).optional(),
|
||||
dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
|
||||
textChunkLimit: z.number().int().positive().optional(),
|
||||
chunkMode: z.enum(["length", "newline"]).optional(),
|
||||
mediaMaxMb: z.number().int().positive().optional(),
|
||||
blockStreaming: z.boolean().optional(),
|
||||
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
|
||||
groups: z
|
||||
.record(
|
||||
z.string(),
|
||||
z
|
||||
.object({
|
||||
requireMention: z.boolean().optional(),
|
||||
tools: ToolPolicySchema,
|
||||
toolsBySender: ToolPolicyBySenderSchema,
|
||||
})
|
||||
.strict()
|
||||
.optional(),
|
||||
)
|
||||
.optional(),
|
||||
ackReaction: z
|
||||
.object({
|
||||
emoji: z.string().optional(),
|
||||
direct: z.boolean().optional().default(true),
|
||||
group: z.enum(["always", "mentions", "never"]).optional().default("mentions"),
|
||||
})
|
||||
.strict()
|
||||
.optional(),
|
||||
debounceMs: z.number().int().nonnegative().optional().default(0),
|
||||
heartbeat: ChannelHeartbeatVisibilitySchema,
|
||||
requireMention: z.boolean().optional(),
|
||||
tools: ToolPolicySchema,
|
||||
toolsBySender: ToolPolicyBySenderSchema,
|
||||
})
|
||||
.strict()
|
||||
.optional();
|
||||
|
||||
const WhatsAppGroupsSchema = z.record(z.string(), WhatsAppGroupEntrySchema).optional();
|
||||
|
||||
const WhatsAppAckReactionSchema = z
|
||||
.object({
|
||||
emoji: z.string().optional(),
|
||||
direct: z.boolean().optional().default(true),
|
||||
group: z.enum(["always", "mentions", "never"]).optional().default("mentions"),
|
||||
})
|
||||
.strict()
|
||||
.optional();
|
||||
|
||||
const WhatsAppSharedSchema = z.object({
|
||||
capabilities: z.array(z.string()).optional(),
|
||||
markdown: MarkdownConfigSchema,
|
||||
configWrites: z.boolean().optional(),
|
||||
sendReadReceipts: z.boolean().optional(),
|
||||
messagePrefix: z.string().optional(),
|
||||
responsePrefix: z.string().optional(),
|
||||
dmPolicy: DmPolicySchema.optional().default("pairing"),
|
||||
selfChatMode: z.boolean().optional(),
|
||||
allowFrom: z.array(z.string()).optional(),
|
||||
groupAllowFrom: z.array(z.string()).optional(),
|
||||
groupPolicy: GroupPolicySchema.optional().default("allowlist"),
|
||||
historyLimit: z.number().int().min(0).optional(),
|
||||
dmHistoryLimit: z.number().int().min(0).optional(),
|
||||
dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
|
||||
textChunkLimit: z.number().int().positive().optional(),
|
||||
chunkMode: z.enum(["length", "newline"]).optional(),
|
||||
blockStreaming: z.boolean().optional(),
|
||||
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
|
||||
groups: WhatsAppGroupsSchema,
|
||||
ackReaction: WhatsAppAckReactionSchema,
|
||||
debounceMs: z.number().int().nonnegative().optional().default(0),
|
||||
heartbeat: ChannelHeartbeatVisibilitySchema,
|
||||
});
|
||||
|
||||
function enforceOpenDmPolicyAllowFromStar(params: {
|
||||
dmPolicy: unknown;
|
||||
allowFrom: unknown;
|
||||
ctx: z.RefinementCtx;
|
||||
message: string;
|
||||
}) {
|
||||
if (params.dmPolicy !== "open") {
|
||||
return;
|
||||
}
|
||||
const allow = (Array.isArray(params.allowFrom) ? params.allowFrom : [])
|
||||
.map((v) => String(v).trim())
|
||||
.filter(Boolean);
|
||||
if (allow.includes("*")) {
|
||||
return;
|
||||
}
|
||||
params.ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["allowFrom"],
|
||||
message: params.message,
|
||||
});
|
||||
}
|
||||
|
||||
export const WhatsAppAccountSchema = WhatsAppSharedSchema.extend({
|
||||
name: z.string().optional(),
|
||||
enabled: z.boolean().optional(),
|
||||
/** Override auth directory for this WhatsApp account (Baileys multi-file auth state). */
|
||||
authDir: z.string().optional(),
|
||||
mediaMaxMb: z.number().int().positive().optional(),
|
||||
})
|
||||
.strict()
|
||||
.superRefine((value, ctx) => {
|
||||
if (value.dmPolicy !== "open") {
|
||||
return;
|
||||
}
|
||||
const allow = (value.allowFrom ?? []).map((v) => String(v).trim()).filter(Boolean);
|
||||
if (allow.includes("*")) {
|
||||
return;
|
||||
}
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["allowFrom"],
|
||||
enforceOpenDmPolicyAllowFromStar({
|
||||
dmPolicy: value.dmPolicy,
|
||||
allowFrom: value.allowFrom,
|
||||
ctx,
|
||||
message: 'channels.whatsapp.accounts.*.dmPolicy="open" requires allowFrom to include "*"',
|
||||
});
|
||||
});
|
||||
|
||||
export const WhatsAppConfigSchema = z
|
||||
.object({
|
||||
accounts: z.record(z.string(), WhatsAppAccountSchema.optional()).optional(),
|
||||
capabilities: z.array(z.string()).optional(),
|
||||
markdown: MarkdownConfigSchema,
|
||||
configWrites: z.boolean().optional(),
|
||||
sendReadReceipts: z.boolean().optional(),
|
||||
dmPolicy: DmPolicySchema.optional().default("pairing"),
|
||||
messagePrefix: z.string().optional(),
|
||||
responsePrefix: z.string().optional(),
|
||||
selfChatMode: z.boolean().optional(),
|
||||
allowFrom: z.array(z.string()).optional(),
|
||||
groupAllowFrom: z.array(z.string()).optional(),
|
||||
groupPolicy: GroupPolicySchema.optional().default("allowlist"),
|
||||
historyLimit: z.number().int().min(0).optional(),
|
||||
dmHistoryLimit: z.number().int().min(0).optional(),
|
||||
dms: z.record(z.string(), DmConfigSchema.optional()).optional(),
|
||||
textChunkLimit: z.number().int().positive().optional(),
|
||||
chunkMode: z.enum(["length", "newline"]).optional(),
|
||||
mediaMaxMb: z.number().int().positive().optional().default(50),
|
||||
blockStreaming: z.boolean().optional(),
|
||||
blockStreamingCoalesce: BlockStreamingCoalesceSchema.optional(),
|
||||
actions: z
|
||||
.object({
|
||||
reactions: z.boolean().optional(),
|
||||
sendMessage: z.boolean().optional(),
|
||||
polls: z.boolean().optional(),
|
||||
})
|
||||
.strict()
|
||||
.optional(),
|
||||
groups: z
|
||||
.record(
|
||||
z.string(),
|
||||
z
|
||||
.object({
|
||||
requireMention: z.boolean().optional(),
|
||||
tools: ToolPolicySchema,
|
||||
toolsBySender: ToolPolicyBySenderSchema,
|
||||
})
|
||||
.strict()
|
||||
.optional(),
|
||||
)
|
||||
.optional(),
|
||||
ackReaction: z
|
||||
.object({
|
||||
emoji: z.string().optional(),
|
||||
direct: z.boolean().optional().default(true),
|
||||
group: z.enum(["always", "mentions", "never"]).optional().default("mentions"),
|
||||
})
|
||||
.strict()
|
||||
.optional(),
|
||||
debounceMs: z.number().int().nonnegative().optional().default(0),
|
||||
heartbeat: ChannelHeartbeatVisibilitySchema,
|
||||
})
|
||||
export const WhatsAppConfigSchema = WhatsAppSharedSchema.extend({
|
||||
accounts: z.record(z.string(), WhatsAppAccountSchema.optional()).optional(),
|
||||
mediaMaxMb: z.number().int().positive().optional().default(50),
|
||||
actions: z
|
||||
.object({
|
||||
reactions: z.boolean().optional(),
|
||||
sendMessage: z.boolean().optional(),
|
||||
polls: z.boolean().optional(),
|
||||
})
|
||||
.strict()
|
||||
.optional(),
|
||||
})
|
||||
.strict()
|
||||
.superRefine((value, ctx) => {
|
||||
if (value.dmPolicy !== "open") {
|
||||
return;
|
||||
}
|
||||
const allow = (value.allowFrom ?? []).map((v) => String(v).trim()).filter(Boolean);
|
||||
if (allow.includes("*")) {
|
||||
return;
|
||||
}
|
||||
ctx.addIssue({
|
||||
code: z.ZodIssueCode.custom,
|
||||
path: ["allowFrom"],
|
||||
enforceOpenDmPolicyAllowFromStar({
|
||||
dmPolicy: value.dmPolicy,
|
||||
allowFrom: value.allowFrom,
|
||||
ctx,
|
||||
message:
|
||||
'channels.whatsapp.dmPolicy="open" requires channels.whatsapp.allowFrom to include "*"',
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user