/**
 * Skill Type Definitions
 *
 * Types for the Skills system, which evolves from the existing SOP
 * (Standard Operating Procedures) system. Skills combine prompts,
 * scripts, environment variables, and browser automation capabilities.
 *
 * @module types/skill.types
 */
// =============================================================================
// Constants
// =============================================================================
/**
 * Valid skill categories
 */
export const SKILL_CATEGORIES = [
    'development',
    'design',
    'communication',
    'research',
    'content-creation',
    'automation',
    'analysis',
    'integration',
    'management',
    'monitoring',
    'memory',
    'system',
    'task-management',
    'quality',
];
/**
 * Display names for skill categories
 */
export const SKILL_CATEGORY_DISPLAY_NAMES = {
    development: 'Development',
    design: 'Design',
    communication: 'Communication',
    research: 'Research',
    'content-creation': 'Content Creation',
    automation: 'Automation',
    analysis: 'Analysis',
    integration: 'Integration',
    management: 'Management',
    monitoring: 'Monitoring',
    memory: 'Memory',
    system: 'System',
    'task-management': 'Task Management',
    quality: 'Quality',
};
/**
 * Valid skill types
 */
export const SKILL_TYPES = ['mcp', 'claude-skill', 'web-page'];
/**
 * Display names for skill types
 */
export const SKILL_TYPE_DISPLAY_NAMES = {
    mcp: 'MCP Integration',
    'claude-skill': 'Claude Skill',
    'web-page': 'Web Page',
};
/**
 * Valid execution types
 */
export const EXECUTION_TYPES = [
    'script',
    'browser',
    'mcp-tool',
    'composite',
    'prompt-only',
];
/**
 * Display names for execution types
 */
export const EXECUTION_TYPE_DISPLAY_NAMES = {
    script: 'Script Execution',
    browser: 'Browser Automation',
    'mcp-tool': 'MCP Tool',
    composite: 'Composite Skill',
    'prompt-only': 'Prompt Only',
};
/**
 * Valid script interpreters
 */
export const SCRIPT_INTERPRETERS = ['bash', 'python', 'node'];
/**
 * Skill system constants
 */
export const SKILL_CONSTANTS = {
    /** Directory paths */
    PATHS: {
        SKILLS_DIR: 'skills',
        SYSTEM_SKILLS_DIR: 'system',
        CUSTOM_SKILLS_DIR: 'custom',
        INDEX_FILE: 'skills-index.json',
        PROMPTS_DIR: 'prompts',
    },
    /** Limits */
    LIMITS: {
        MAX_NAME_LENGTH: 100,
        MAX_DESCRIPTION_LENGTH: 500,
        MAX_PROMPT_LENGTH: 50000,
        MAX_TRIGGERS: 50,
        MAX_TAGS: 20,
        MAX_ASSIGNABLE_ROLES: 50,
        MAX_COMPOSITE_SKILLS: 10,
        DEFAULT_SCRIPT_TIMEOUT_MS: 60000,
        MAX_SCRIPT_TIMEOUT_MS: 300000,
    },
    /** Default values */
    DEFAULTS: {
        VERSION: '1.0.0',
        SCRIPT_TIMEOUT_MS: 60000,
        IS_ENABLED: true,
        IS_BUILTIN: false,
    },
};
// =============================================================================
// Type Guard Functions
// =============================================================================
/**
 * Check if a value is a valid skill category
 *
 * @param value - Value to check
 * @returns True if value is a valid SkillCategory
 */
export function isValidSkillCategory(value) {
    return SKILL_CATEGORIES.includes(value);
}
/**
 * Check if a value is a valid skill type
 *
 * @param value - Value to check
 * @returns True if value is a valid SkillType
 */
export function isValidSkillType(value) {
    return SKILL_TYPES.includes(value);
}
/**
 * Check if a value is a valid execution type
 *
 * @param value - Value to check
 * @returns True if value is a valid SkillExecutionType
 */
export function isValidExecutionType(value) {
    return EXECUTION_TYPES.includes(value);
}
/**
 * Check if a value is a valid script interpreter
 *
 * @param value - Value to check
 * @returns True if value is a valid ScriptInterpreter
 */
export function isValidScriptInterpreter(value) {
    return SCRIPT_INTERPRETERS.includes(value);
}
// =============================================================================
// Utility Functions
// =============================================================================
/**
 * Create a skill with default values from minimal input
 *
 * @param input - Required input fields for creating a skill
 * @returns A complete Skill object with default values
 */
export function createDefaultSkill(input) {
    const now = new Date().toISOString();
    const id = `skill-${input.name.toLowerCase().replace(/\s+/g, '-')}-${Date.now()}`;
    return {
        id,
        name: input.name,
        description: input.description,
        category: input.category,
        skillType: input.skillType ?? 'claude-skill',
        promptFile: `${id}/instructions.md`,
        assignableRoles: [],
        triggers: [],
        tags: [],
        version: SKILL_CONSTANTS.DEFAULTS.VERSION,
        isBuiltin: SKILL_CONSTANTS.DEFAULTS.IS_BUILTIN,
        isEnabled: SKILL_CONSTANTS.DEFAULTS.IS_ENABLED,
        createdAt: now,
        updatedAt: now,
    };
}
/**
 * Convert a Skill to a SkillSummary for list views
 *
 * @param skill - Full skill object
 * @returns SkillSummary with derived fields
 */
export function skillToSummary(skill) {
    return {
        id: skill.id,
        name: skill.name,
        description: skill.description,
        category: skill.category,
        skillType: skill.skillType,
        executionType: skill.execution?.type ?? 'prompt-only',
        triggerCount: skill.triggers?.length ?? 0,
        roleCount: skill.assignableRoles?.length ?? 0,
        isBuiltin: skill.isBuiltin,
        isEnabled: skill.isEnabled,
        notices: skill.notices,
        runtime: skill.runtime,
    };
}
/**
 * Convert a Skill to storage format (omits isBuiltin since that's determined by location)
 *
 * @param skill - Full skill object
 * @returns SkillStorageFormat for JSON serialization
 */
export function skillToStorageFormat(skill) {
    return {
        id: skill.id,
        name: skill.name,
        description: skill.description,
        category: skill.category,
        skillType: skill.skillType,
        promptFile: skill.promptFile,
        execution: skill.execution,
        environment: skill.environment,
        runtime: skill.runtime,
        notices: skill.notices,
        assignableRoles: skill.assignableRoles,
        triggers: skill.triggers,
        tags: skill.tags,
        version: skill.version,
        createdAt: skill.createdAt,
        updatedAt: skill.updatedAt,
    };
}
/**
 * Convert storage format back to a Skill
 *
 * @param storage - Stored skill data
 * @param isBuiltin - Whether this skill comes from the system directory
 * @returns Full Skill object
 */
export function storageFormatToSkill(storage, isBuiltin) {
    return {
        ...storage,
        skillType: storage.skillType ?? 'claude-skill', // Default for backward compatibility
        isBuiltin,
        isEnabled: true, // Default to enabled when loading
    };
}
/**
 * Get display name for a skill category
 *
 * @param category - Skill category
 * @returns Human-readable display name
 */
export function getSkillCategoryDisplayName(category) {
    return SKILL_CATEGORY_DISPLAY_NAMES[category] ?? category;
}
/**
 * Get display name for an execution type
 *
 * @param executionType - Execution type
 * @returns Human-readable display name
 */
export function getExecutionTypeDisplayName(executionType) {
    return EXECUTION_TYPE_DISPLAY_NAMES[executionType] ?? executionType;
}
// =============================================================================
// Validation Functions
// =============================================================================
/**
 * Validate CreateSkillInput
 *
 * @param input - Input to validate
 * @returns Array of error messages (empty if valid)
 */
export function validateCreateSkillInput(input) {
    const errors = [];
    // Required fields
    if (!input.name || input.name.trim().length === 0) {
        errors.push('Name is required');
    }
    else if (input.name.length > SKILL_CONSTANTS.LIMITS.MAX_NAME_LENGTH) {
        errors.push(`Name must be ${SKILL_CONSTANTS.LIMITS.MAX_NAME_LENGTH} characters or less`);
    }
    if (!input.description || input.description.trim().length === 0) {
        errors.push('Description is required');
    }
    else if (input.description.length > SKILL_CONSTANTS.LIMITS.MAX_DESCRIPTION_LENGTH) {
        errors.push(`Description must be ${SKILL_CONSTANTS.LIMITS.MAX_DESCRIPTION_LENGTH} characters or less`);
    }
    if (!isValidSkillCategory(input.category)) {
        errors.push(`Invalid category: ${input.category}`);
    }
    if (!input.promptContent || input.promptContent.trim().length === 0) {
        errors.push('Prompt content is required');
    }
    else if (input.promptContent.length > SKILL_CONSTANTS.LIMITS.MAX_PROMPT_LENGTH) {
        errors.push(`Prompt content must be ${SKILL_CONSTANTS.LIMITS.MAX_PROMPT_LENGTH} characters or less`);
    }
    // Optional fields validation
    if (input.triggers && input.triggers.length > SKILL_CONSTANTS.LIMITS.MAX_TRIGGERS) {
        errors.push(`Maximum ${SKILL_CONSTANTS.LIMITS.MAX_TRIGGERS} triggers allowed`);
    }
    if (input.tags && input.tags.length > SKILL_CONSTANTS.LIMITS.MAX_TAGS) {
        errors.push(`Maximum ${SKILL_CONSTANTS.LIMITS.MAX_TAGS} tags allowed`);
    }
    if (input.assignableRoles &&
        input.assignableRoles.length > SKILL_CONSTANTS.LIMITS.MAX_ASSIGNABLE_ROLES) {
        errors.push(`Maximum ${SKILL_CONSTANTS.LIMITS.MAX_ASSIGNABLE_ROLES} assignable roles allowed`);
    }
    // Execution config validation
    if (input.execution) {
        errors.push(...validateSkillExecution(input.execution));
    }
    return errors;
}
/**
 * Validate UpdateSkillInput
 *
 * @param input - Input to validate
 * @returns Array of error messages (empty if valid)
 */
export function validateUpdateSkillInput(input) {
    const errors = [];
    if (input.name !== undefined) {
        if (input.name.trim().length === 0) {
            errors.push('Name cannot be empty');
        }
        else if (input.name.length > SKILL_CONSTANTS.LIMITS.MAX_NAME_LENGTH) {
            errors.push(`Name must be ${SKILL_CONSTANTS.LIMITS.MAX_NAME_LENGTH} characters or less`);
        }
    }
    if (input.description !== undefined) {
        if (input.description.trim().length === 0) {
            errors.push('Description cannot be empty');
        }
        else if (input.description.length > SKILL_CONSTANTS.LIMITS.MAX_DESCRIPTION_LENGTH) {
            errors.push(`Description must be ${SKILL_CONSTANTS.LIMITS.MAX_DESCRIPTION_LENGTH} characters or less`);
        }
    }
    if (input.category !== undefined && !isValidSkillCategory(input.category)) {
        errors.push(`Invalid category: ${input.category}`);
    }
    if (input.promptContent !== undefined) {
        if (input.promptContent.trim().length === 0) {
            errors.push('Prompt content cannot be empty');
        }
        else if (input.promptContent.length > SKILL_CONSTANTS.LIMITS.MAX_PROMPT_LENGTH) {
            errors.push(`Prompt content must be ${SKILL_CONSTANTS.LIMITS.MAX_PROMPT_LENGTH} characters or less`);
        }
    }
    if (input.triggers && input.triggers.length > SKILL_CONSTANTS.LIMITS.MAX_TRIGGERS) {
        errors.push(`Maximum ${SKILL_CONSTANTS.LIMITS.MAX_TRIGGERS} triggers allowed`);
    }
    if (input.tags && input.tags.length > SKILL_CONSTANTS.LIMITS.MAX_TAGS) {
        errors.push(`Maximum ${SKILL_CONSTANTS.LIMITS.MAX_TAGS} tags allowed`);
    }
    if (input.assignableRoles &&
        input.assignableRoles.length > SKILL_CONSTANTS.LIMITS.MAX_ASSIGNABLE_ROLES) {
        errors.push(`Maximum ${SKILL_CONSTANTS.LIMITS.MAX_ASSIGNABLE_ROLES} assignable roles allowed`);
    }
    if (input.execution) {
        errors.push(...validateSkillExecution(input.execution));
    }
    return errors;
}
/**
 * Validate skill execution configuration
 *
 * @param config - Execution configuration to validate
 * @returns Array of error messages (empty if valid)
 */
export function validateSkillExecution(config) {
    const errors = [];
    if (!isValidExecutionType(config.type)) {
        errors.push(`Invalid execution type: ${config.type}`);
        return errors;
    }
    switch (config.type) {
        case 'script':
            if (!config.script) {
                errors.push('Script configuration required for script type');
            }
            else {
                if (!config.script.file || config.script.file.trim().length === 0) {
                    errors.push('Script file path is required');
                }
                if (!isValidScriptInterpreter(config.script.interpreter)) {
                    errors.push(`Invalid script interpreter: ${config.script.interpreter}`);
                }
                if (config.script.timeoutMs !== undefined &&
                    config.script.timeoutMs > SKILL_CONSTANTS.LIMITS.MAX_SCRIPT_TIMEOUT_MS) {
                    errors.push(`Script timeout cannot exceed ${SKILL_CONSTANTS.LIMITS.MAX_SCRIPT_TIMEOUT_MS}ms`);
                }
            }
            break;
        case 'browser':
            if (!config.browser) {
                errors.push('Browser configuration required for browser type');
            }
            else {
                if (!config.browser.url || config.browser.url.trim().length === 0) {
                    errors.push('Browser URL is required');
                }
                if (!config.browser.instructions || config.browser.instructions.trim().length === 0) {
                    errors.push('Browser instructions are required');
                }
            }
            break;
        case 'mcp-tool':
            if (!config.mcpTool) {
                errors.push('MCP tool configuration required for mcp-tool type');
            }
            else if (!config.mcpTool.toolName || config.mcpTool.toolName.trim().length === 0) {
                errors.push('MCP tool name is required');
            }
            break;
        case 'composite':
            if (!config.composite) {
                errors.push('Composite configuration required for composite type');
            }
            else {
                if (!config.composite.skillSequence || config.composite.skillSequence.length === 0) {
                    errors.push('Composite skill must have at least one skill in sequence');
                }
                else if (config.composite.skillSequence.length > SKILL_CONSTANTS.LIMITS.MAX_COMPOSITE_SKILLS) {
                    errors.push(`Composite skill cannot have more than ${SKILL_CONSTANTS.LIMITS.MAX_COMPOSITE_SKILLS} skills`);
                }
            }
            break;
        case 'prompt-only':
            // No additional config required for prompt-only
            break;
    }
    return errors;
}
/**
 * Check if a skill matches the given filter
 *
 * @param skill - Skill to check
 * @param filter - Filter criteria
 * @returns True if skill matches all filter criteria
 */
export function matchesSkillFilter(skill, filter) {
    if (filter.category !== undefined && skill.category !== filter.category) {
        return false;
    }
    if (filter.executionType !== undefined) {
        const skillType = skill.execution?.type ?? 'prompt-only';
        if (skillType !== filter.executionType) {
            return false;
        }
    }
    if (filter.roleId !== undefined && !skill.assignableRoles.includes(filter.roleId)) {
        return false;
    }
    if (filter.isBuiltin !== undefined && skill.isBuiltin !== filter.isBuiltin) {
        return false;
    }
    if (filter.isEnabled !== undefined && skill.isEnabled !== filter.isEnabled) {
        return false;
    }
    if (filter.search !== undefined && filter.search.trim().length > 0) {
        const searchLower = filter.search.toLowerCase();
        const matchesName = skill.name.toLowerCase().includes(searchLower);
        const matchesDescription = skill.description.toLowerCase().includes(searchLower);
        const matchesTriggers = skill.triggers.some((t) => t.toLowerCase().includes(searchLower));
        if (!matchesName && !matchesDescription && !matchesTriggers) {
            return false;
        }
    }
    if (filter.tags !== undefined && filter.tags.length > 0) {
        const hasAllTags = filter.tags.every((tag) => skill.tags.some((t) => t.toLowerCase() === tag.toLowerCase()));
        if (!hasAllTags) {
            return false;
        }
    }
    return true;
}
//# sourceMappingURL=skill.types.js.map