import * as z from "zod/mini"; import { createGeneration, type Generation, generationSchema, } from "./v3-generation.js"; const canonicalIdStringSchema = z.string().check(z.trim(), z.minLength(1)); const envelopeSchema = z.object({ t: z.string().check(z.startsWith("getuserfeedback:")), gen: generationSchema, viewId: z.optional(canonicalIdStringSchema), }); const recoveryRetryOperationSchema = z.enum([ "prefetch", "prerender", "close", "init", "configure", ]); const recoveryRetryReasonSchema = z.enum(["network", "timeout", "unknown"]); const recoveryRetryPolicySchema = z.object({ attempts: z.optional(z.number().check(z.int(), z.minimum(1))), backoffMs: z.optional(z.number().check(z.int(), z.minimum(0))), }); const recoveryRetryHintSchema = z.object({ operation: recoveryRetryOperationSchema, policy: z.optional(recoveryRetryPolicySchema), reason: z.optional(recoveryRetryReasonSchema), }); export const recoveryHintSchema = z.object({ resetViewState: z.optional(z.boolean()), retry: z.optional(recoveryRetryHintSchema), }); /** Loader → Core: Error notification */ export const eventErrorSchema = z.extend(envelopeSchema, { t: z.literal("getuserfeedback:event:error"), code: z.string(), instanceId: z.optional(canonicalIdStringSchema), details: z.optional(z.unknown()), recovery: z.optional(recoveryHintSchema), }); export type RecoveryRetryOperation = z.output< typeof recoveryRetryOperationSchema >; export type RecoveryRetryReason = z.output; export type RecoveryRetryHint = z.output; export type RecoveryHint = z.output; export type EventError = z.output; function toGeneration(gen: number | Generation): Generation { return typeof gen === "number" ? createGeneration(gen) : gen; } export function buildEventError(params: { gen: number | Generation; code: string; instanceId?: string; details?: unknown; recovery?: RecoveryHint; }): EventError { const base: EventError = { t: "getuserfeedback:event:error", gen: toGeneration(params.gen), code: params.code, instanceId: params.instanceId, details: params.details, }; if (params.recovery) { return { ...base, recovery: params.recovery }; } return base; } export function isEventError(msg: unknown): msg is EventError { return eventErrorSchema.safeParse(msg).success; }