import type { LlmClient } from "../llm/types.js";
import type { SkillScript, ExecutionReport } from "../browser/script-runner.js";
export interface SkillInfo {
    name: string;
    description: string;
    kind: "script" | "instruction" | "invalid";
    stepsCount?: number;
    builtin?: boolean;
    readonly?: boolean;
}
export interface LoadedInstructionSkill {
    name: string;
    description: string;
    content: string;
    builtin?: boolean;
    readonly?: boolean;
    truncated?: boolean;
    originalChars?: number;
}
export declare const SKILL_CONTENT_LIMITS: {
    readonly fileMaxChars: number;
    readonly readMaxChars: number;
    readonly autoLoadMaxSkills: 4;
    readonly autoLoadPerSkillMaxChars: number;
    readonly autoLoadTotalMaxChars: number;
    readonly listMaxSkills: 200;
    readonly listMaxChars: number;
};
/**
 * Validate that `steps` is a non-empty array of {action: string, params: object, ...}.
 * Returns null on success, or a human-readable error string.
 *
 * Used at every skill load / save / install entry point to keep malformed
 * steps from reaching ScriptRunner (where `resolveVariables` on a missing
 * params object throws before step-level fallback can recover) AND to
 * disambiguate "this JSON array is actually steps" from "this JSON array
 * is just an example payload in an instruction skill" in extractStepsJson.
 */
export declare function validateSkillSteps(steps: unknown): string | null;
export declare function extractStepsJson(content: string): string | null;
export declare class SkillGenerator {
    private skillsDir;
    private llmClient;
    constructor(workspace: string, llmClient: LlmClient);
    private resolveBuiltinSkill;
    isBuiltinSkill(skillRef: string): boolean;
    getAutoLoadedInstructionSkills(text: string): LoadedInstructionSkill[];
    renderLoadedInstructionSkillSection(skills: LoadedInstructionSkill[]): string;
    renderAutoLoadedInstructionSkillSection(text: string): string;
    /** Generate a skill from an execution log file */
    generate(logFilePath: string): Promise<string>;
    /** Save a skill to a markdown file with metadata */
    saveSkill(skill: SkillScript, meta?: {
        usageCount?: number;
        successRate?: number;
        lastImproved?: string;
    }): string;
    /** Save a markdown instruction skill exactly as authored, adding dipclaw metadata if missing. */
    saveInstructionSkill(name: string, content: string, meta?: {
        usageCount?: number;
        successRate?: number;
        lastImproved?: string;
    }): string;
    /**
     * Resolve a skill reference to an absolute file path, or null if not found.
     * Strips a trailing ".md" before sanitizing so callers can pass either
     * "foo" or "foo.md". Falls back to the raw ref iff it's a safe single-
     * segment basename — no path traversal.
     */
    private resolveSkillPath;
    /** True if a user-installed workspace skill exists for this reference/name. */
    workspaceSkillExists(skillRef: string): boolean;
    private resolveSkillFile;
    private readSkillFileContent;
    /** True if a skill file already exists for this reference/name. */
    skillExists(skillRef: string): boolean;
    /** Load a skill from a markdown file */
    loadSkill(skillRef: string): SkillScript | null;
    /** Read capped markdown content of a skill file, or null if missing. */
    readSkillFile(skillRef: string): string | null;
    /** Return lightweight metadata for both executable scripts and instruction skills. */
    getSkillInfo(skillRef: string): SkillInfo | null;
    /** Delete a skill file. Returns true if removed, false if not found. */
    deleteSkill(skillRef: string): boolean;
    /** List all available skills */
    listSkills(): string;
    /** Load metadata from a skill file */
    loadSkillMeta(skillRef: string): {
        usageCount: number;
        successRate: number;
        lastImproved: string;
    };
    /** Update usage stats for a skill after execution */
    updateSkillMeta(skillRef: string, success: boolean): void;
    /**
     * Determine if an execution log is worth auto-generating a skill from.
     * Criteria: enough meaningful browser actions, all successful, not trivially short.
     */
    shouldAutoGenerate(logFilePath: string): boolean;
    /**
     * Heuristic: does the task prompt request structured cross-run state?
     * If so, a linear script can't enforce that correctly (see comment in
     * shouldAutoGenerate). Match is intentionally broad — false positives
     * (keep something LLM-driven that could have been a script) are cheap;
     * false negatives can produce visible repeated or stale work.
     *
     * Exported as a static helper so tests / future call sites can reuse it
     * without instantiating SkillGenerator.
     */
    static isStorageSensitivePrompt(prompt: string): boolean;
    /**
     * Improve a skill based on its execution report.
     * When steps used LLM fallback, ask the LLM to revise those steps.
     */
    improveSkill(skill: SkillScript, report: ExecutionReport): Promise<string | null>;
}
