Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 | import { normalizeAccountId } from "../sdk/helpers.ts"; import { z } from "zod"; export { z }; import { buildSecretInputSchema, hasConfiguredSecretInput } from "../secret-input.ts"; const DmPolicySchema = z.enum(["open", "pairing", "allowlist"]); const GroupPolicySchema = z.enum(["open", "allowlist", "disabled"]); const ToolPolicySchema = z .object({ allow: z.array(z.string()).optional(), deny: z.array(z.string()).optional(), }) .strict() .optional(); /** * Group session scope for routing DingTalk group messages. * - "group" (default): one session per group chat * - "group_sender": one session per (group + sender) */ const GroupSessionScopeSchema = z .enum(["group", "group_sender"]) .optional(); /** * Dingtalk tools configuration. * Controls which tool categories are enabled. */ const DingtalkToolsConfigSchema = z .object({ docs: z.boolean().optional(), // Document operations (default: true) media: z.boolean().optional(), // Media upload operations (default: true) }) .strict() .optional(); export const DingtalkGroupSchema = z .object({ requireMention: z.boolean().optional(), tools: ToolPolicySchema, enabled: z.boolean().optional(), allowFrom: z.array(z.union([z.string(), z.number()])).optional(), systemPrompt: z.string().optional(), groupSessionScope: GroupSessionScopeSchema, }) .strict(); const DingtalkSharedConfigShape = { dmPolicy: DmPolicySchema.optional(), allowFrom: z.array(z.union([z.string(), z.number()])).optional(), groupPolicy: GroupPolicySchema.optional(), groupAllowFrom: z.array(z.union([z.string(), z.number()])).optional(), requireMention: z.boolean().optional(), groups: z.record(z.string(), DingtalkGroupSchema.optional()).optional(), historyLimit: z.number().int().min(0).optional(), dmHistoryLimit: z.number().int().min(0).optional(), textChunkLimit: z.number().int().positive().optional(), mediaMaxMb: z.number().positive().optional(), tools: DingtalkToolsConfigSchema, typingIndicator: z.boolean().optional(), resolveSenderNames: z.boolean().optional(), separateSessionByConversation: z.boolean().optional(), groupSessionScope: GroupSessionScopeSchema, asyncMode: z.boolean().optional(), ackText: z.string().optional(), endpoint: z.string().optional(), // DWClient gateway endpoint debug: z.boolean().optional(), // DWClient debug mode }; /** * Per-account configuration. * All fields are optional - missing fields inherit from top-level config. */ export const DingtalkAccountConfigSchema = z .object({ enabled: z.boolean().optional(), name: z.string().optional(), // Display name for this account clientId: z.union([z.string(), z.number()]).optional(), clientSecret: buildSecretInputSchema().optional(), ...DingtalkSharedConfigShape, }) .strict(); export const DingtalkConfigSchema = z .object({ enabled: z.boolean().optional(), defaultAccount: z.string().optional(), // Top-level credentials (backward compatible for single-account mode) clientId: z.union([z.string(), z.number()]).optional(), clientSecret: buildSecretInputSchema().optional(), enableMediaUpload: z.boolean().optional(), systemPrompt: z.string().optional(), ...DingtalkSharedConfigShape, dmPolicy: DmPolicySchema.optional().default("open"), groupPolicy: GroupPolicySchema.optional().default("open"), requireMention: z.boolean().optional().default(true), separateSessionByConversation: z.boolean().optional().default(true), groupSessionScope: GroupSessionScopeSchema.optional().default("group"), // Multi-account configuration accounts: z.record(z.string(), DingtalkAccountConfigSchema.optional()).optional(), }) .strict() .superRefine((value, ctx) => { const defaultAccount = value.defaultAccount?.trim(); if (defaultAccount && value.accounts && Object.keys(value.accounts).length > 0) { const normalizedDefaultAccount = normalizeAccountId(defaultAccount); if (!Object.prototype.hasOwnProperty.call(value.accounts, normalizedDefaultAccount)) { ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["defaultAccount"], message: `channels.dingtalk-connector.defaultAccount="${defaultAccount}" does not match a configured account key`, }); } } // Validate dmPolicy and allowFrom consistency if (value.dmPolicy === "allowlist") { const allowFrom = value.allowFrom ?? []; if (allowFrom.length === 0) { ctx.addIssue({ code: z.ZodIssueCode.custom, path: ["allowFrom"], message: 'channels.dingtalk-connector.dmPolicy="allowlist" requires channels.dingtalk-connector.allowFrom to contain at least one entry', }); } } }); |