import * as z from "zod/mini"; export const attentionPolicySourceSchema = z.enum(["default", "custom"]); export const attentionExclusiveSurfaceStrategySchema = z.enum(["queue"]); export const attentionBlockedBroadcastStrategySchema = z.enum(["queue"]); const legacyAttentionPolicyConfigFields = { version: z.string().check(z.trim(), z.minLength(1)), source: attentionPolicySourceSchema, recentFlowCooldownMs: z.number().check(z.positive()), exclusiveSurfaceStrategy: attentionExclusiveSurfaceStrategySchema, blockedBroadcastStrategy: attentionBlockedBroadcastStrategySchema, }; export const legacyAttentionPolicyConfigSchema = z.strictObject( legacyAttentionPolicyConfigFields, ); // V2 is the additive policy envelope for the flow-display wire contract. // Keep legacy strict, and add future policy controls here instead of creating // another versioned sibling field for every new setting. export const attentionPolicyConfigSchema = z.looseObject({ ...legacyAttentionPolicyConfigFields, recentInAppCooldownMs: z._default(z.number().check(z.nonnegative()), 0), automaticInAppWeeklyLimit: z.optional( z.number().check(z.int(), z.positive()), ), }); export type AttentionPolicyConfig = z.output< typeof attentionPolicyConfigSchema >; export type ResolvedAttentionPolicyConfig = AttentionPolicyConfig & { automaticInAppWeeklyLimit: number; }; export const DEFAULT_ATTENTION_POLICY_CONFIG: ResolvedAttentionPolicyConfig = { version: "attention-policy-default-v1", source: "default", recentFlowCooldownMs: 5 * 60 * 1000, recentInAppCooldownMs: 0, automaticInAppWeeklyLimit: 3, exclusiveSurfaceStrategy: "queue", blockedBroadcastStrategy: "queue", };