/**
 * Zod Schema for LLM Output Validation
 *
 * Validates the raw output from the LLM before further processing.
 * This schema is used with getAiResponse() for structured output.
 *
 * IMPORTANT: OpenAI structured output requires all schema fields to have explicit types.
 * We cannot use z.any() - it must be replaced with explicit union types.
 */
import { z } from 'zod';
import type { BlockCategory } from '../../config/types';
import type { CustomCssRuleInput, CustomCssAtRuleInput } from '../../contracts';
/**
 * LLM-compatible theme patch operation schema.
 * Uses discriminated union for the 3 operation types.
 */
export declare const llmThemePatchOpSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
    op: z.ZodLiteral<"add">;
    path: z.ZodString;
    value: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodObject<{
        name: z.ZodString;
        hex: z.ZodString;
    }, z.core.$strip>, z.ZodArray<z.ZodObject<{
        name: z.ZodString;
        hex: z.ZodString;
    }, z.core.$strip>>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>;
}, z.core.$strip>, z.ZodObject<{
    op: z.ZodLiteral<"replace">;
    path: z.ZodString;
    value: z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodObject<{
        name: z.ZodString;
        hex: z.ZodString;
    }, z.core.$strip>, z.ZodArray<z.ZodObject<{
        name: z.ZodString;
        hex: z.ZodString;
    }, z.core.$strip>>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>;
}, z.core.$strip>, z.ZodObject<{
    op: z.ZodLiteral<"remove">;
    path: z.ZodString;
}, z.core.$strip>], "op">;
export type ThemePatchOp = z.infer<typeof llmThemePatchOpSchema>;
/**
 * LLM-compatible custom CSS rule schema.
 * Uses array of declarations instead of record for OpenAI compatibility.
 */
export declare const llmCustomCssRuleSchema: z.ZodObject<{
    id: z.ZodString;
    selector: z.ZodString;
    declarations: z.ZodArray<z.ZodObject<{
        property: z.ZodString;
        value: z.ZodString;
    }, z.core.$strip>>;
}, z.core.$strip>;
/**
 * LLM-compatible nested rule schema for @media/@supports rules.
 * Uses array of declarations instead of record for OpenAI compatibility.
 */
export declare const llmNestedRuleSchema: z.ZodObject<{
    selector: z.ZodString;
    declarations: z.ZodArray<z.ZodObject<{
        property: z.ZodString;
        value: z.ZodString;
    }, z.core.$strip>>;
}, z.core.$strip>;
/**
 * LLM-compatible @media at-rule schema.
 */
export declare const llmMediaAtRuleSchema: z.ZodObject<{
    id: z.ZodString;
    type: z.ZodLiteral<"media">;
    query: z.ZodString;
    rules: z.ZodArray<z.ZodObject<{
        selector: z.ZodString;
        declarations: z.ZodArray<z.ZodObject<{
            property: z.ZodString;
            value: z.ZodString;
        }, z.core.$strip>>;
    }, z.core.$strip>>;
}, z.core.$strip>;
/**
 * LLM-compatible at-rule schema.
 * For now, only supports @media rules from LLM output.
 * Other at-rules (@keyframes, @font-face, @supports) can be added manually if needed.
 */
export declare const llmAtRuleSchema: z.ZodObject<{
    id: z.ZodString;
    type: z.ZodLiteral<"media">;
    query: z.ZodString;
    rules: z.ZodArray<z.ZodObject<{
        selector: z.ZodString;
        declarations: z.ZodArray<z.ZodObject<{
            property: z.ZodString;
            value: z.ZodString;
        }, z.core.$strip>>;
    }, z.core.$strip>>;
}, z.core.$strip>;
/**
 * Convert array-of-declarations format to record format.
 * LLM outputs: [{ property: "fontSize", value: "3rem" }]
 * Runtime expects: { fontSize: "3rem" }
 */
export declare function normalizeDeclarationsArrayToRecord(declarations: Array<{
    property: string;
    value: string;
}>): Record<string, string>;
/**
 * Normalize LLM CSS rule output to runtime format.
 */
export declare function normalizeLlmCssRule(rule: z.infer<typeof llmCustomCssRuleSchema>): {
    id: string;
    selector: string;
    declarations: Record<string, string>;
};
/**
 * Normalize LLM nested rule output to runtime format.
 */
export declare function normalizeLlmNestedRule(rule: z.infer<typeof llmNestedRuleSchema>): {
    selector: string;
    declarations: Record<string, string>;
};
/**
 * Normalize LLM @media at-rule output to runtime format.
 */
export declare function normalizeLlmMediaAtRule(atRule: z.infer<typeof llmMediaAtRuleSchema>): {
    id: string;
    type: 'media';
    query: string;
    rules: Array<{
        selector: string;
        declarations: Record<string, string>;
    }>;
};
/**
 * Combined field schema for LLM output.
 * Supports: text, richText, media, boolean, link, select, number, group, repeater.
 */
declare const llmFieldSchema: z.ZodUnion<readonly [z.ZodObject<{
    id: z.ZodString;
    label: z.ZodString;
    description: z.ZodNullable<z.ZodString>;
    required: z.ZodBoolean;
    defaultValue: z.ZodNullable<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>;
    type: z.ZodLiteral<"text">;
    multiline: z.ZodBoolean;
    maxLength: z.ZodNullable<z.ZodNumber>;
}, z.core.$strip>, z.ZodObject<{
    id: z.ZodString;
    label: z.ZodString;
    description: z.ZodNullable<z.ZodString>;
    required: z.ZodBoolean;
    defaultValue: z.ZodNullable<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>;
    type: z.ZodLiteral<"richText">;
}, z.core.$strip>, z.ZodObject<{
    id: z.ZodString;
    label: z.ZodString;
    description: z.ZodNullable<z.ZodString>;
    required: z.ZodBoolean;
    defaultValue: z.ZodNullable<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>;
    type: z.ZodLiteral<"media">;
    mediaKinds: z.ZodNullable<z.ZodArray<z.ZodEnum<{
        image: "image";
        video: "video";
        audio: "audio";
        document: "document";
        spreadsheet: "spreadsheet";
        archive: "archive";
    }>>>;
}, z.core.$strip>, z.ZodObject<{
    id: z.ZodString;
    label: z.ZodString;
    description: z.ZodNullable<z.ZodString>;
    required: z.ZodBoolean;
    defaultValue: z.ZodNullable<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>;
    type: z.ZodLiteral<"boolean">;
}, z.core.$strip>, z.ZodObject<{
    id: z.ZodString;
    label: z.ZodString;
    description: z.ZodNullable<z.ZodString>;
    required: z.ZodBoolean;
    defaultValue: z.ZodNullable<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>;
    type: z.ZodLiteral<"link">;
}, z.core.$strip>, z.ZodObject<{
    id: z.ZodString;
    label: z.ZodString;
    description: z.ZodNullable<z.ZodString>;
    required: z.ZodBoolean;
    defaultValue: z.ZodNullable<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>;
    type: z.ZodLiteral<"select">;
    options: z.ZodArray<z.ZodObject<{
        value: z.ZodString;
        label: z.ZodString;
    }, z.core.$strip>>;
    multiple: z.ZodNullable<z.ZodBoolean>;
}, z.core.$strip>, z.ZodObject<{
    id: z.ZodString;
    label: z.ZodString;
    description: z.ZodNullable<z.ZodString>;
    required: z.ZodBoolean;
    defaultValue: z.ZodNullable<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>;
    type: z.ZodLiteral<"number">;
}, z.core.$strip>, z.ZodObject<{
    id: z.ZodString;
    label: z.ZodString;
    description: z.ZodNullable<z.ZodString>;
    required: z.ZodBoolean;
    defaultValue: z.ZodNullable<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>;
    type: z.ZodLiteral<"group">;
    schema: z.ZodObject<{
        fields: z.ZodArray<z.ZodObject<{
            id: z.ZodString;
            type: z.ZodString;
            label: z.ZodString;
            required: z.ZodNullable<z.ZodBoolean>;
            multiline: z.ZodNullable<z.ZodBoolean>;
            defaultValue: z.ZodNullable<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>;
        }, z.core.$loose>>;
    }, z.core.$strip>;
}, z.core.$strip>, z.ZodObject<{
    id: z.ZodString;
    label: z.ZodString;
    description: z.ZodNullable<z.ZodString>;
    required: z.ZodBoolean;
    defaultValue: z.ZodNullable<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>;
    type: z.ZodLiteral<"repeater">;
    itemLabel: z.ZodString;
    itemLabelSource: z.ZodNullable<z.ZodString>;
    minItems: z.ZodNumber;
    maxItems: z.ZodNullable<z.ZodNumber>;
    allowConversion: z.ZodBoolean;
    schema: z.ZodObject<{
        fields: z.ZodArray<z.ZodObject<{
            id: z.ZodString;
            type: z.ZodString;
            label: z.ZodString;
            required: z.ZodNullable<z.ZodBoolean>;
            multiline: z.ZodNullable<z.ZodBoolean>;
            defaultValue: z.ZodNullable<z.ZodUnion<readonly [z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>, z.ZodArray<z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean, z.ZodNull]>>]>>;
        }, z.core.$loose>>;
    }, z.core.$strip>;
}, z.core.$strip>]>;
/**
 * Field definition type inferred from schema.
 */
type LlmFieldDefinition = z.infer<typeof llmFieldSchema>;
/**
 * Maximum nesting depth for layout nodes.
 * OpenAI structured output has ~10 level limit; we use 6 for real-world layouts.
 * Depth 6 means: root → level1 → level2 → level3 → level4 → level5 → level6 (leaf)
 *
 * Why 6?
 * - Real-world footer navigation needs 5 levels
 * - 6 provides headroom for complex layouts
 * - Uses ~9 Zod nesting levels (1-level margin from OpenAI's 10)
 */
export declare const MAX_LAYOUT_DEPTH = 6;
export declare const llmNodeSchema: z.ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
/**
 * Node definition type inferred from schema.
 */
export type LlmNodeDefinition = z.infer<typeof llmNodeSchema>;
/**
 * LLM custom block - uses LLM-specific schemas for OpenAI compatibility.
 * All properties required (nullable for optional ones) per OpenAI's requirements.
 */
export interface LlmCustomBlock {
    id: `custom.${string}`;
    title: string;
    titleSource: string | string[] | null;
    description: string | null;
    category: BlockCategory;
    icon: string | null;
    tags: string[] | null;
    fields: LlmFieldDefinition[];
    layout: LlmNodeDefinition;
}
/**
 * Complete LLM output structure.
 * All properties required (nullable for optional ones) per OpenAI's requirements.
 */
export interface HtmlToManifestOutputSchema {
    blocks: LlmCustomBlock[];
    themePatch: ThemePatchOp[] | null;
    customCssRules: CustomCssRuleInput[] | null;
    customCssAtRules: CustomCssAtRuleInput[] | null;
    /**
     * Explanation of fixes made in retry attempts.
     * Nullable on first attempt, but strongly requested on retries for debugging.
     */
    fixRationale: string | null;
}
/**
 * LLM output schema for custom block definitions.
 *
 * Uses simplified LLM-compatible schemas (no z.any()) for OpenAI structured output.
 * All properties required (nullable for optional ones) per OpenAI's requirements.
 * Full validation happens after parsing via validateLayout().
 *
 * Note: Explicit type annotation required due to recursive schema complexity.
 */
export declare const llmCustomBlockSchema: z.ZodType<LlmCustomBlock>;
/**
 * Schema for the complete LLM output.
 *
 * This is used with getAiResponse({ kind: 'json', schema }) for
 * structured output generation.
 * All properties required (nullable for optional ones) per OpenAI's requirements.
 *
 * Note: Explicit type annotation required due to complex nested types.
 */
export declare const htmlToManifestOutputSchema: z.ZodType<HtmlToManifestOutputSchema>;
/**
 * Validation error with actionable feedback for LLM self-correction.
 */
export interface ValidationError {
    path: string;
    message: string;
    suggestion?: string;
}
/**
 * Collect validation errors from a parsed output.
 *
 * Goes beyond Zod schema validation to check:
 * - Node types are whitelisted
 * - Transform IDs are whitelisted
 * - $bind references match defined fields
 * - Content nodes have bindings (text, richText, media, button, link)
 * - All defined fields are used in the layout
 * - Redundant link/text nodes in repeaters
 */
export declare function collectValidationErrors(output: HtmlToManifestOutputSchema): ValidationError[];
type FieldDef = {
    id: string;
    type: string;
    schema?: {
        fields?: FieldDef[];
    } | null;
};
/**
 * Detect redundant link label patterns in repeaters.
 *
 * A common LLM mistake: when iterating over a repeater with link fields,
 * the LLM creates both:
 * 1. A link/button node with links.label transform (correct - displays the label)
 * 2. A separate text node binding to item.label (redundant - duplicates the label)
 *
 * This validation detects when a container has sibling nodes where:
 * - One is a link/button with links.label transform
 * - Another is a text node binding to a label-like field from the same item
 */
declare function detectRedundantLinkLabels(node: unknown, blockId: string, fields: FieldDef[], path?: string, repeatStack?: Array<{
    itemName: string;
    fields: FieldDef[];
}>): ValidationError[];
/**
 * Find redundant text nodes that duplicate link labels in a set of sibling nodes.
 */
declare function findRedundantLinkTextSiblings(children: Array<Record<string, unknown>>, repeatStack: Array<{
    itemName: string;
    fields: FieldDef[];
}>, parentPath: string): Array<{
    path: string;
    message: string;
    suggestion: string;
}>;
/**
 * Check if a text binding is redundant given a link binding with links.label.
 * Returns info about the redundant label field, or null if not redundant.
 */
declare function checkRedundantLabelBinding(linkBindFrom: string, textBindFrom: string, repeatStack: Array<{
    itemName: string;
    fields: FieldDef[];
}>): {
    labelField: string;
} | null;
/**
 * Calculate the maximum depth of a layout tree.
 * Returns 0 for a leaf node, increments for each level of nesting.
 */
export declare function getMaxDepth(node: unknown, currentDepth?: number): number;
/**
 * Detect if layout was likely truncated at depth limit.
 * Returns paths to container nodes at max depth that have children: null.
 *
 * This helps identify when the LLM wanted to create deeper structures but
 * was constrained by the schema depth limit.
 */
export declare function detectPotentialTruncation(node: unknown, maxAllowedDepth: number, currentDepth?: number, path?: string): string[];
/**
 * Format validation errors as actionable feedback for LLM self-correction.
 */
export declare function formatValidationFeedback(errors: ValidationError[], output?: HtmlToManifestOutputSchema): string;
/**
 * Export internal functions for testing.
 * These are not part of the public API.
 * @internal
 */
export declare const __testing: {
    detectRedundantLinkLabels: typeof detectRedundantLinkLabels;
    findRedundantLinkTextSiblings: typeof findRedundantLinkTextSiblings;
    checkRedundantLabelBinding: typeof checkRedundantLabelBinding;
};
export {};
