import type { GoodVibesConfig, ConfigKey, ConfigValue, ConfigSetting } from './schema.js';
import type { HookDispatcher } from '../hooks/index.js';
/** Deep immutable type — prevents mutation of nested objects returned from getAll(). */
export type DeepReadonly<T> = {
    readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
/** Constructor overrides for CLI args and programmatic instantiation. */
interface ConfigCliOverrides {
    model?: string | undefined;
    autoApprove?: boolean | undefined;
    systemPromptFile?: string | undefined;
    workingDir?: string | undefined;
    surfaceRoot?: string | undefined;
}
export type ConfigOverrides = ConfigCliOverrides & ({
    configDir: string;
    homeDir?: string | undefined;
    sharedConfigPath?: string | undefined;
} | {
    homeDir: string;
    configDir?: string | undefined;
    sharedConfigPath?: string | undefined;
});
export interface ConfigSetOptions {
    bypassManagedLock?: boolean | undefined;
}
/** Callback invoked when a watched config key changes. */
export type ConfigChangeCallback<K extends ConfigKey> = (newValue: ConfigValue<K>, oldValue: ConfigValue<K>) => void;
/** Unsubscribe handle returned by ConfigManager.subscribe(). */
export type ConfigUnsubscribe = () => void;
/**
 * ConfigManager — Layered, mutable, persistent config system.
 *
 * Load order: defaults < global surface settings < project surface settings < CLI overrides
 * API keys are never persisted — loaded from env vars only.
 */
export declare class ConfigManager {
    private config;
    private readonly configDir;
    private readonly configPath;
    private readonly projectConfigPath;
    private readonly workingDirectory;
    private readonly homeDirectory;
    private hookDispatcher;
    private readonly _listeners;
    constructor(overrides: ConfigOverrides);
    getControlPlaneConfigDir(): string;
    getWorkingDirectory(): string | null;
    getHomeDirectory(): string | null;
    attachHookDispatcher(hookDispatcher: Pick<HookDispatcher, 'fire'> | null): void;
    private resolvePath;
    /** Get a config value by dot-path key. */
    get<K extends ConfigKey>(key: K): ConfigValue<K>;
    /** Set a config value by dot-path key and auto-save to disk. */
    set<K extends ConfigKey>(key: K, value: ConfigValue<K>, options?: ConfigSetOptions): void;
    /**
     * Subscribe to changes on a specific config key.
     * Returns an unsubscribe function. Safe to call multiple times.
     */
    subscribe<K extends ConfigKey>(key: K, cb: ConfigChangeCallback<K>): ConfigUnsubscribe;
    /** Notify synchronous subscribers of a key change. */
    private notifyListeners;
    /**
     * Fire the Change:config hook for a config key change.
     */
    private emitConfigHook;
    /**
     * Set a config value from a validated ConfigKey with unknown value type.
     * Used when iterating schema entries where the value type cannot be statically
     * inferred. Runtime validation is still applied by the underlying set() method.
     */
    setDynamic(key: ConfigKey, value: unknown, options?: ConfigSetOptions): void;
    /** Return a deep-readonly snapshot of the full config. Nested objects are immutable. */
    getAll(): DeepReadonly<GoodVibesConfig>;
    /** Return a deep-cloned snapshot of a config category. */
    getCategory<C extends keyof GoodVibesConfig>(category: C): Readonly<GoodVibesConfig[C]>;
    /** Return a deep-cloned snapshot of the live config. Safe for read-only external consumers. */
    getRaw(): Readonly<GoodVibesConfig>;
    /** Return the full schema. */
    getSchema(): ConfigSetting[];
    /** Persist current config to global TUI settings file. */
    save(): void;
    /** Persist current config to the project-level surface settings file. */
    saveProject(): void;
    /** Load config from disk: global then project (project wins). Deep-merges with defaults. */
    load(): void;
    /**
     * Merge a partial patch into a config category and auto-save.
     *
     * This is the correct way to update array or object fields within a category
     * that cannot be expressed as a scalar dot-path key (e.g. notifications.webhookUrls).
     * The patch is shallow-merged into the existing category value.
     */
    mergeCategory<C extends keyof GoodVibesConfig>(category: C, patch: Partial<GoodVibesConfig[C]>): void;
    /**
     * Reset a specific key to its default, or reset all config.
     * Saves to disk after reset.
     */
    reset(key?: ConfigKey): void;
}
export {};
//# sourceMappingURL=manager.d.ts.map