import { z } from 'zod';

interface Logger {
    debug(message: string, meta?: Record<string, unknown>): void;
    info(message: string, meta?: Record<string, unknown>): void;
    warn(message: string, meta?: Record<string, unknown>): void;
    error(message: string, meta?: Record<string, unknown>): void;
}

interface OperatorParameter {
    name: string;
    label?: string;
    group?: string;
    page?: string;
    type?: string;
    dataType?: string;
    defaultValue?: unknown;
    minValue?: unknown;
    maxValue?: unknown;
    menuItems?: string[];
    menuLabels?: string[];
    description?: string;
}
interface OperatorDoc {
    id?: string | null;
    name: string;
    displayName?: string;
    category?: string;
    subcategory?: string;
    version?: string;
    description?: string;
    summary?: string;
    usage?: string;
    tips?: string[];
    warnings?: string[];
    parameters?: OperatorParameter[];
    pythonExamples?: unknown[];
    codeExamples?: unknown[];
    commonInputs?: unknown;
    commonOutputs?: unknown;
    relatedOperators?: string[];
    keywords?: string[];
    tags?: string[];
}
interface OperatorSummary {
    slug: string;
    name: string;
    displayName: string;
    category: string;
    subcategory: string;
    summary: string;
    keywords: string[];
}
interface PythonMember {
    name?: string;
    id?: string;
    returnType?: string;
    readOnly?: boolean;
    description?: string;
}
interface PythonMethodParam {
    name?: string;
    type?: string;
}
interface PythonMethod {
    name?: string;
    parameters?: PythonMethodParam[];
    returns?: string;
    signature?: string;
    description?: string;
}
interface PythonClass {
    className: string;
    displayName?: string;
    description?: string;
    category?: string;
    members?: PythonMember[];
    methods?: PythonMethod[];
}
interface PythonClassSummary {
    className: string;
    displayName: string;
    category: string;
    methodCount: number;
    memberCount: number;
}
interface Pattern {
    id: string;
    name: string;
    description?: string;
    category?: string;
    workflow?: string[];
    use_case?: string;
}
interface PatternSummary {
    id: string;
    name: string;
    category: string;
    description: string;
}
interface GlslCode {
    language?: string;
    filename?: string;
    snippet?: string;
}
interface GlslTechnique {
    id: string;
    name: string;
    subcategory?: string;
    description?: string;
    difficulty?: string;
    operators?: string[];
    tags?: string[];
    notes?: string;
    code?: GlslCode;
    setup?: string;
}
interface GlslSummary {
    id: string;
    name: string;
    description: string;
    difficulty: string;
}
interface Tutorial {
    id: string;
    name: string;
    displayName?: string;
    category?: string;
    subcategory?: string;
    description?: string;
    summary?: string;
    content?: string;
    keywords?: string[];
    tags?: string[];
}
interface TutorialSummary {
    id: string;
    name: string;
    category: string;
    summary: string;
}
interface KnowledgeStats {
    source: "local" | "bottobot" | "empty";
    operators: number;
    pythonClasses: number;
    patterns: number;
    glsl: number;
    tutorials: number;
}

interface KnowledgeBaseOptions {
    dataDir?: string;
    logger?: Logger;
}
/**
 * Read-only accessor over the embedded TouchDesigner knowledge base. Prefers the
 * imported local data directory; falls back to reading directly from an installed
 * `@bottobot/td-mcp`; otherwise degrades to empty results (never throws on lookup).
 */
declare class KnowledgeBase {
    private readonly logger;
    private readonly source;
    private opIndexCache?;
    private opLookupCache?;
    private readonly opDocCache;
    private pyIndexCache?;
    private pyLookupCache?;
    private readonly pyDocCache;
    private tutIndexCache?;
    private tutLookupCache?;
    private readonly tutDocCache;
    private patternsCache?;
    private glslCache?;
    constructor(options?: KnowledgeBaseOptions);
    private static resolveSource;
    private readJson;
    private listJsonFiles;
    private operatorIndex;
    private operatorLookup;
    listOperatorCategories(): string[];
    listOperators(category?: string): OperatorSummary[];
    getOperator(nameOrSlug: string): OperatorDoc | undefined;
    /** Soft existence check (by operator type, display name, or slug). */
    operatorExists(typeOrName: string): boolean;
    searchOperators(query: string, limit?: number): OperatorSummary[];
    private pythonIndex;
    private pythonLookup;
    listPythonClasses(): PythonClassSummary[];
    getPythonClass(name: string): PythonClass | undefined;
    private patterns;
    listPatterns(): PatternSummary[];
    getPattern(name: string): Pattern | undefined;
    private glsl;
    listGlslPatterns(): GlslSummary[];
    getGlslPattern(name: string): GlslTechnique | undefined;
    private tutorialIndex;
    private tutorialLookup;
    listTutorials(): TutorialSummary[];
    getTutorial(name: string): Tutorial | undefined;
    get sourceKind(): KnowledgeStats["source"];
    stats(): KnowledgeStats;
}

declare const RecipeSchema: z.ZodObject<{
    id: z.ZodString;
    name: z.ZodString;
    description: z.ZodDefault<z.ZodString>;
    tags: z.ZodDefault<z.ZodArray<z.ZodString>>;
    difficulty: z.ZodDefault<z.ZodEnum<{
        beginner: "beginner";
        intermediate: "intermediate";
        advanced: "advanced";
    }>>;
    td_version_min: z.ZodDefault<z.ZodString>;
    nodes: z.ZodArray<z.ZodObject<{
        name: z.ZodString;
        type: z.ZodString;
        parameters: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
        parent: z.ZodOptional<z.ZodString>;
        render: z.ZodOptional<z.ZodBoolean>;
        comment: z.ZodOptional<z.ZodString>;
    }, z.core.$strip>>;
    connections: z.ZodDefault<z.ZodArray<z.ZodObject<{
        from: z.ZodString;
        to: z.ZodString;
        from_output: z.ZodDefault<z.ZodNumber>;
        to_input: z.ZodDefault<z.ZodNumber>;
    }, z.core.$strip>>>;
    parameters: z.ZodDefault<z.ZodArray<z.ZodObject<{
        name: z.ZodString;
        node: z.ZodString;
        param: z.ZodString;
        value: z.ZodOptional<z.ZodUnknown>;
        label: z.ZodOptional<z.ZodString>;
        min: z.ZodOptional<z.ZodNumber>;
        max: z.ZodOptional<z.ZodNumber>;
        description: z.ZodOptional<z.ZodString>;
    }, z.core.$strip>>>;
    glsl_uniforms: z.ZodDefault<z.ZodArray<z.ZodObject<{
        node: z.ZodString;
        name: z.ZodString;
        kind: z.ZodDefault<z.ZodEnum<{
            float: "float";
            vec: "vec";
            color: "color";
        }>>;
        value: z.ZodOptional<z.ZodUnion<readonly [z.ZodNumber, z.ZodArray<z.ZodNumber>]>>;
        label: z.ZodOptional<z.ZodString>;
        min: z.ZodOptional<z.ZodNumber>;
        max: z.ZodOptional<z.ZodNumber>;
        description: z.ZodOptional<z.ZodString>;
    }, z.core.$strip>>>;
    glsl_code: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
    python_code: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
    preview_description: z.ZodDefault<z.ZodString>;
}, z.core.$strip>;
type Recipe = z.infer<typeof RecipeSchema>;
interface RecipeSummary {
    id: string;
    name: string;
    description: string;
    tags: string[];
    difficulty: Recipe["difficulty"];
}

interface RecipeLibraryOptions {
    dir?: string;
    logger?: Logger;
}
/** Loads and validates recipe JSON files from the recipes directory. */
declare class RecipeLibrary {
    private readonly dir;
    private readonly logger;
    private cache?;
    constructor(options?: RecipeLibraryOptions);
    private load;
    all(): Recipe[];
    list(): RecipeSummary[];
    get(id: string): Recipe | undefined;
    /** Finds the best recipe whose tags/name/description match any of the given terms. */
    findByTags(terms: string[]): Recipe | undefined;
}

/** Input shape for creating a node (used by the client and Layer 3 tool). */
declare const CreateNodeInputSchema: z.ZodObject<{
    parent_path: z.ZodString;
    type: z.ZodString;
    name: z.ZodOptional<z.ZodString>;
    parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
}, z.core.$strip>;
type CreateNodeInput = z.infer<typeof CreateNodeInputSchema>;
/** A single atomic operation accepted by `POST /api/batch`. */
declare const BatchOperationSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
    action: z.ZodLiteral<"create">;
    parent_path: z.ZodString;
    type: z.ZodString;
    name: z.ZodOptional<z.ZodString>;
    parameters: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
}, z.core.$strip>, z.ZodObject<{
    action: z.ZodLiteral<"update">;
    path: z.ZodString;
    parameters: z.ZodRecord<z.ZodString, z.ZodUnknown>;
}, z.core.$strip>, z.ZodObject<{
    action: z.ZodLiteral<"delete">;
    path: z.ZodString;
}, z.core.$strip>, z.ZodObject<{
    action: z.ZodLiteral<"connect">;
    source_path: z.ZodString;
    target_path: z.ZodString;
    source_output: z.ZodDefault<z.ZodNumber>;
    target_input: z.ZodDefault<z.ZodNumber>;
}, z.core.$strip>], "action">;
type TdBatchOperation = z.infer<typeof BatchOperationSchema>;

interface TouchDesignerClientOptions {
    baseUrl: string;
    timeoutMs?: number;
    logger?: Logger;
    /** Optional shared bearer token; sent as `Authorization: Bearer <token>` when set. */
    token?: string;
    /** Overridable for tests (defaults to global `fetch`). */
    fetchImpl?: typeof fetch;
}
/**
 * HTTP client for the TouchDesigner REST bridge. Every method maps to one of the
 * endpoints in the bridge spec. All failures surface as typed `TdError`s so MCP
 * tool handlers can convert them into friendly messages without crashing.
 */
declare class TouchDesignerClient {
    private readonly baseUrl;
    private readonly timeoutMs;
    private readonly logger;
    private readonly token;
    private readonly fetchImpl;
    constructor(options: TouchDesignerClientOptions);
    get endpoint(): string;
    private request;
    getInfo(): Promise<{
        td_version?: string | undefined;
        python_version?: string | undefined;
        build?: string | undefined;
        bridge_version?: string | undefined;
        project?: string | undefined;
    }>;
    createNode(input: CreateNodeInput): Promise<{
        path: string;
        type: string;
        name: string;
    }>;
    deleteNode(path: string): Promise<{
        deleted: string;
    }>;
    getNodes(parentPath?: string): Promise<{
        nodes: {
            path: string;
            type: string;
            name: string;
        }[];
    }>;
    getNode(path: string): Promise<{
        path: string;
        type: string;
        name: string;
        parameters: Record<string, unknown>;
        inputs?: string[] | undefined;
        outputs?: string[] | undefined;
        family?: string | undefined;
        errors?: string[] | undefined;
    }>;
    updateNodeParameters(path: string, parameters: Record<string, unknown>): Promise<{
        path: string;
        type: string;
        name: string;
        parameters: Record<string, unknown>;
        inputs?: string[] | undefined;
        outputs?: string[] | undefined;
        family?: string | undefined;
        errors?: string[] | undefined;
    }>;
    executePythonScript(script: string, returnOutput?: boolean): Promise<{
        result?: unknown;
        stdout?: string | undefined;
        printed?: string[] | undefined;
    }>;
    execNodeMethod(path: string, method: string, args?: unknown[], kwargs?: Record<string, unknown>): Promise<{
        result: unknown;
    }>;
    getNodeErrors(path: string): Promise<{
        errors: {
            path: string;
            message: string;
            type?: string | undefined;
        }[];
    }>;
    getPreview(path: string, width?: number, height?: number): Promise<{
        path: string;
        width: number;
        height: number;
        format: string;
        base64: string;
    }>;
    batch(operations: TdBatchOperation[]): Promise<{
        results: {
            action: string;
            ok: boolean;
            path?: string | undefined;
            data?: unknown;
            error?: string | undefined;
        }[];
    }>;
    getNetworkErrors(path: string): Promise<{
        errors: {
            path: string;
            message: string;
            type?: string | undefined;
        }[];
    }>;
    getNetworkTopology(path: string, recursive?: boolean): Promise<{
        nodes: {
            path: string;
            type: string;
            name: string;
        }[];
        connections: {
            source_path: string;
            source_output: number;
            target_path: string;
            target_input: number;
        }[];
    }>;
    getNetworkPerformance(path: string): Promise<{
        nodes: {
            path: string;
            cook_time_ms: number;
            cook_count?: number | undefined;
        }[];
        total_cook_time_ms?: number | undefined;
        gpu_memory_mb?: number | undefined;
    }>;
}

/** Shared dependencies injected into every tool handler (keeps handlers testable). */
interface ToolContext {
    client: TouchDesignerClient;
    knowledge: KnowledgeBase;
    recipes: RecipeLibrary;
    logger: Logger;
    /**
     * Whether the raw Python escape-hatch tools may be registered. Undefined means
     * allowed (the default); only an explicit `false` locks them out.
     */
    allowRawPython?: boolean;
}

interface CliResult {
    stdout: string;
    stderr: string;
    code: number;
}
interface RunCliOptions {
    /** Inject a context (used by tests); production builds one from env config. */
    makeCtx?: () => ToolContext;
}
declare function runCli(argv: string[], opts?: RunCliOptions): Promise<CliResult>;

export { type CliResult, type RunCliOptions, runCli };
