/**
 * Core persona management operations
 */
import { Persona } from '../types/persona.js';
import { PersonaElement, PersonaElementMetadata } from './PersonaElement.js';
import { FileLockManager } from '../security/fileLockManager.js';
import { IndicatorConfig } from '../config/indicator-config.js';
import { PortfolioManager } from '../portfolio/PortfolioManager.js';
import { StateChangeNotifier } from '../services/StateChangeNotifier.js';
import { PersonaImporter, ImportResult } from './export-import/PersonaImporter.js';
import { BaseElementManager, type BaseElementManagerOptions } from '../elements/base/BaseElementManager.js';
import { ValidationRegistry } from '../services/validation/ValidationRegistry.js';
import { MetadataService } from '../services/MetadataService.js';
import { FileOperationsService } from '../services/FileOperationsService.js';
interface PersonaManagerOptions extends BaseElementManagerOptions {
    personaImporter?: PersonaImporter;
    notifier?: StateChangeNotifier;
}
export declare class PersonaManager extends BaseElementManager<PersonaElement> {
    /**
     * Track active personas by filename (stable identifier)
     * Issue #281: Changed from single active persona to Set for multiple active
     */
    private activePersonas;
    private currentUser;
    private indicatorConfig;
    protected portfolioManager: PortfolioManager;
    protected fileLockManager: FileLockManager;
    private personaImporter?;
    private notifier?;
    private readonly personasDir;
    private pathValidatorInitialized;
    private triggerValidationService;
    private validationService;
    private metadataService;
    private readonly serializationService;
    constructor(portfolioManager: PortfolioManager, indicatorConfig: IndicatorConfig, fileLockManager: FileLockManager, fileOperationsService: FileOperationsService, validationRegistry: ValidationRegistry, metadataService: MetadataService, personaImporter?: PersonaImporter, notifier?: StateChangeNotifier, baseOptions?: PersonaManagerOptions);
    /**
     * Override to return singular form for element type labeling.
     */
    protected getElementLabel(): string;
    /**
     * Initialize and load all personas
     */
    initialize(): Promise<void>;
    /**
     * Reload personas using BaseElementManager caches
     */
    reload(): Promise<void>;
    private deriveFilename;
    private clonePersona;
    private normalizePersonaForSave;
    /**
     * Get all loaded personas as a Map (used by import operations)
     */
    getAllPersonas(): Promise<Map<string, Persona>>;
    /**
     * Get personas from cache as a Map (synchronous, for DI consumers)
     */
    getPersonas(): Map<string, Persona>;
    /**
     * List all personas as an array
     * Ensures all personas have filenames set
     */
    list(): Promise<PersonaElement[]>;
    /**
     * Reload personas and return MCP-formatted response
     */
    reloadPersonas(): Promise<{
        content: {
            type: string;
            text: string;
        }[];
    }>;
    /**
     * Find a persona by identifier (filename, name, or unique_id)
     * Uses cached elements from BaseElementManager for synchronous access
     * Multi-strategy search: filename (with/without .md), name (case-insensitive), unique_id
     */
    /** Cache miss metrics for monitoring persona lookup health (Issue #843) */
    private cacheMissMetrics;
    /** Get cache miss metrics for monitoring and diagnostics */
    getCacheMissMetrics(): Readonly<typeof this.cacheMissMetrics>;
    /**
     * Check if a persona matches an identifier by filename, name, or ID.
     * Shared matching logic used by both findPersona() and findPersonaAsync().
     */
    private matchesIdentifier;
    findPersona(identifier: string): PersonaElement | undefined;
    /** In-flight disk lookups to prevent duplicate reads for the same identifier */
    private pendingLookups;
    /**
     * Find a persona with disk fallback when cache misses.
     *
     * Issue #843: findPersona() is synchronous and cache-only. After LRU eviction
     * or direct filesystem edits followed by scan(), personas become invisible even
     * though the file exists on disk. This async method tries the fast cache path
     * first, then falls back to BaseElementManager.findByName() which has the full
     * cache → storage index → direct file load → list scan fallback chain.
     *
     * Includes request deduplication: concurrent lookups for the same identifier
     * share a single disk read to avoid redundant I/O in bridge/swarm scenarios.
     */
    findPersonaAsync(identifier: string): Promise<PersonaElement | undefined>;
    /**
     * Perform the actual disk lookup for findPersonaAsync.
     * Separated to support request deduplication.
     */
    private performDiskLookup;
    /**
     * Activate a persona
     * Issue #281: Now supports multiple active personas (adds to set instead of replacing)
     * Issue #843: Now async — uses findPersonaAsync() to recover from cache eviction
     */
    activatePersona(identifier: string): Promise<{
        success: boolean;
        message: string;
        persona?: Persona;
    }>;
    /**
     * Deactivate a specific persona by name
     * Issue #281: Now requires a name parameter to deactivate specific persona from the set
     */
    deactivatePersona(identifier?: string): {
        success: boolean;
        message: string;
    };
    /**
     * Get the first active persona (for backward compatibility)
     * Issue #281: With multiple active personas, returns the first one
     */
    getActivePersona(): PersonaElement | null;
    /**
     * Get all active personas
     * Issue #281: New method to get all active personas
     */
    getActivePersonas(): PersonaElement[];
    /**
     * Get identifier for the first active persona (filename).
     * Issue #281: For backward compatibility, returns first active persona ID
     */
    getActivePersonaId(): string | null;
    /**
     * Get all active persona IDs (filenames)
     * Issue #281: New method to get all active persona IDs
     */
    getActivePersonaIds(): string[];
    /**
     * Check if a specific persona is active
     * Issue #281: New method to check if a persona is active
     */
    isPersonaActive(identifier: string): boolean;
    /**
     * Get persona indicator for responses
     * Issue #281: Now supports multiple active personas - concatenates all indicators
     */
    getPersonaIndicator(): string;
    /**
     * Build persona metadata with default values and optional overrides
     *
     * @param validatedInputs - Validated input data
     * @param metadataOverrides - Optional metadata overrides from user
     * @returns Complete PersonaMetadata object
     */
    private buildPersonaMetadata;
    /**
     * Validate and sanitize all persona creation inputs
     * SECURITY: Phase 4.3 - Added Unicode validation to all text inputs
     * SECURITY: Phase 4.1 - Block ALL invalid content, not just critical
     * SECURITY: Phase 4.7 - Accept normalized content even if Unicode issues were detected and fixed
     *
     * @param name - Raw persona name
     * @param description - Raw persona description
     * @param instructions - Raw persona instructions
     * @param triggers - Optional comma-separated trigger words
     * @returns Validated and sanitized inputs ready for metadata construction
     * @throws Error if validation fails
     */
    private validatePersonaInputs;
    /**
     * Validates metadata keys to prevent prototype pollution
     * @throws Error if dangerous keys are detected
     * @private
     */
    private validateMetadataKeys;
    /**
     * Create a new persona following the unified element manager pattern.
     *
     * This is the primary API for persona creation, replacing the deprecated
     * `createPersona()` and `createNewPersona()` methods (v2 breaking change).
     *
     * @param data - Persona creation options
     * @param data.name - Display name for the persona (required)
     * @param data.description - Short description of the persona's purpose
     * @param data.instructions - Behavioral instructions (alias: content)
     * @param data.category - Optional category for organization
     * @param data.triggers - Optional keywords that activate this persona
     * @returns The created PersonaElement
     * @throws {Error} If validation fails or persona already exists
     *
     * @example
     * // Basic persona creation
     * const persona = await personaManager.create({
     *   name: 'Code Reviewer',
     *   description: 'Expert at reviewing code for quality',
     *   instructions: 'You are a meticulous code reviewer...'
     * });
     *
     * @example
     * // With category and triggers
     * const persona = await personaManager.create({
     *   name: 'Technical Writer',
     *   description: 'Specializes in clear documentation',
     *   instructions: 'You write clear, concise documentation...',
     *   category: 'professional',
     *   triggers: ['docs', 'documentation', 'readme']
     * });
     *
     * @example
     * // Minimal creation (defaults applied)
     * const persona = await personaManager.create({
     *   name: 'Quick Helper'
     * });
     *
     * @since v2.0.0 - Replaces createPersona() and createNewPersona()
     */
    create(data: Partial<PersonaElementMetadata> & {
        content?: string;
        instructions?: string;
    }): Promise<PersonaElement>;
    /**
     * Edit an existing persona
     */
    editPersona(personaIdentifier: string, field: string, value: string): Promise<{
        success: boolean;
        message: string;
        isDefault: boolean;
        newName: string;
        version: string | undefined;
        newId: string | undefined;
    }>;
    /**
     * Edit existing persona and return the updated persona (for PersonaHandler compatibility)
     */
    editExistingPersona(persona: PersonaElement, field: string, value: string): Promise<PersonaElement>;
    /**
     * Validate a persona and return a formatted report
     */
    validatePersona(personaIdentifier: string): {
        success: boolean;
        message: string;
        report: import("../index.barrel.js").ElementValidationResult;
    };
    /**
     * Set current user identity
     * SECURITY: Phase 4.6 - Added username and email validation
     */
    setUserIdentity(username: string | null, email?: string): void;
    /**
     * Get current user identity
     */
    getUserIdentity(): {
        username: string | null;
        email: string | null;
    };
    /**
     * Clear user identity
     */
    clearUserIdentity(): void;
    /**
     * Update indicator configuration
     */
    updateIndicatorConfig(config: IndicatorConfig): void;
    /**
     * Get current indicator configuration
     */
    getIndicatorConfig(): IndicatorConfig;
    /**
     * Helper to get current user for attribution
     * REFACTORED: Now delegates to MetadataService for consistent user attribution
     */
    getCurrentUserForAttribution(): string;
    /**
     * Reset internal state; aligns PersonaManager with DI lifecycle hooks.
     * CRITICAL: Must call super.dispose() to clean up file watchers and prevent open handles
     */
    dispose(): void;
    /**
     * Check if active set cleanup is needed and perform cleanup if necessary
     * Issue #83: Active element limit enforcement for personas
     * @private
     */
    private checkAndCleanupActiveSet;
    /**
     * Clean up stale entries from active personas set
     * Issue #83: Validates that all active personas still exist and removes orphaned references
     * @private
     */
    private cleanupStaleActivePersonas;
    private notifyPersonaChange;
    private initializePathValidator;
    /**
     * Override delete to handle auto-deactivation before deletion.
     * FIX: Issue #281 - Unified delete pattern for standard element-crud flow
     *
     * @param filePath - The filename of the persona to delete
     */
    delete(filePath: string): Promise<void>;
    /**
     * Delete persona by name or identifier (legacy API)
     * @deprecated Use delete(filename) via standard element-crud flow
     */
    deletePersona(personaIdentifier: string): Promise<{
        success: boolean;
        message: string;
    }>;
    importPersona(source: string, overwrite?: boolean): Promise<ImportResult>;
    /**
     * Convert PersonaMetadata (legacy) to PersonaElementMetadata (new standard)
     * Ensures strict typing for age_rating and generation_method
     * NOTE: Filename is infrastructure data, not business metadata - it's excluded here
     */
    private toPersonaElementMetadata;
    /**
     * Type guard to check if metadata is PersonaElementMetadata
     */
    private isPersonaElementMetadata;
    protected parseMetadata(data: any): Promise<PersonaElementMetadata>;
    protected createElement(metadata: PersonaElementMetadata, bodyText: string): PersonaElement;
    protected serializeElement(element: PersonaElement): Promise<string>;
    getFileExtension(): string;
    importElement(data: string, format?: 'json' | 'yaml' | 'markdown'): Promise<PersonaElement>;
    exportElement(persona: PersonaElement, _format?: 'json' | 'yaml' | 'markdown'): Promise<string>;
    protected canDelete(element: PersonaElement): Promise<{
        allowed: boolean;
        reason?: string;
    }>;
    protected beforeSave(persona: PersonaElement): Promise<void>;
}
export {};
//# sourceMappingURL=PersonaManager.d.ts.map