/**
 * Crann v2 Store
 *
 * The central state hub that runs in the service worker.
 * This is NOT a singleton - each call to createStore() returns a new instance.
 */
import type { BrowserLocation } from "../transport";
import { ConfigSchema, ValidatedConfig, StoreOptions, DerivedState, DerivedSharedState, DerivedAgentState, StateChangeListener, AgentConnectionInfo } from "./types";
export declare class Store<TConfig extends ConfigSchema> {
    private readonly config;
    private readonly options;
    private readonly porter;
    private readonly stateManager;
    private readonly persistence;
    private readonly agentRegistry;
    private readonly actionExecutor;
    private readonly stateChangeListeners;
    private readonly agentConnectListeners;
    private readonly agentDisconnectListeners;
    private isDestroyed;
    constructor(config: ValidatedConfig<TConfig>, options?: StoreOptions);
    /**
     * Get the current shared state (state visible to all agents).
     *
     * @returns A snapshot of the current shared state
     * @throws {LifecycleError} If the store has been destroyed
     *
     * @example
     * const state = store.getState();
     * console.log(state.count);
     */
    getState(): DerivedState<TConfig>;
    /**
     * Get agent-scoped state for a specific agent.
     *
     * @param agentId - The unique identifier of the agent
     * @returns The agent-scoped state for the specified agent
     * @throws {LifecycleError} If the store has been destroyed
     *
     * @example
     * store.onAgentConnect((agent) => {
     *   const agentState = store.getAgentState(agent.id);
     * });
     */
    getAgentState(agentId: string): DerivedAgentState<TConfig>;
    /**
     * Update shared state. Changes are persisted and broadcast to all agents.
     *
     * @param state - Partial state to merge with current shared state
     * @throws {LifecycleError} If the store has been destroyed
     *
     * @example
     * await store.setState({ count: 5 });
     */
    setState(state: Partial<DerivedSharedState<TConfig>>): Promise<void>;
    /**
     * Update state for a specific agent. Can include both shared and agent-scoped state.
     *
     * @param state - Partial state to merge
     * @param agentId - The agent to update (for agent-scoped state)
     * @throws {LifecycleError} If the store has been destroyed
     *
     * @example
     * await store.setState({ count: 5, agentData: 'custom' }, agentId);
     */
    setState(state: Partial<DerivedState<TConfig>>, agentId: string): Promise<void>;
    /**
     * Update agent-scoped state for a specific agent.
     *
     * @param agentId - The unique identifier of the agent
     * @param state - Partial agent-scoped state to merge
     * @throws {LifecycleError} If the store has been destroyed
     *
     * @example
     * await store.setAgentState(agentId, { agentData: 'custom' });
     */
    setAgentState(agentId: string, state: Partial<DerivedAgentState<TConfig>>): Promise<void>;
    /**
     * Clear all state back to defaults and remove persisted data.
     *
     * @throws {LifecycleError} If the store has been destroyed
     *
     * @example
     * await store.clear();
     */
    clear(): Promise<void>;
    /**
     * Subscribe to state changes. Called whenever state is updated.
     *
     * Can subscribe to all changes or filter by specific keys.
     *
     * @param callbackOrKeys - Either a callback for all changes, or an array of keys to filter by
     * @param maybeCallback - Callback when first arg is keys array
     * @returns Unsubscribe function
     * @throws {LifecycleError} If the store has been destroyed
     *
     * @example
     * // Subscribe to all changes
     * const unsubscribe = store.subscribe((state, changes, agent) => {
     *   console.log('State changed:', changes);
     * });
     *
     * // Subscribe to specific keys only
     * const unsubscribe = store.subscribe(['active', 'initialized'], (state, changes, agent) => {
     *   // Only called when 'active' or 'initialized' change
     *   console.log('Relevant state changed:', changes);
     * });
     */
    subscribe(callbackOrKeys: StateChangeListener<TConfig> | Array<keyof DerivedState<TConfig>>, maybeCallback?: StateChangeListener<TConfig>): () => void;
    /**
     * Register callback for when an agent connects.
     *
     * @param callback - Called with agent connection info
     * @returns Unsubscribe function
     * @throws {LifecycleError} If the store has been destroyed
     *
     * @example
     * store.onAgentConnect((agent) => {
     *   console.log(`Agent ${agent.id} connected from tab ${agent.tabId}`);
     * });
     */
    onAgentConnect(callback: (agent: AgentConnectionInfo) => void): () => void;
    /**
     * Register callback for when an agent disconnects.
     *
     * @param callback - Called with agent connection info
     * @returns Unsubscribe function
     * @throws {LifecycleError} If the store has been destroyed
     *
     * @example
     * store.onAgentDisconnect((agent) => {
     *   console.log(`Agent ${agent.id} disconnected`);
     * });
     */
    onAgentDisconnect(callback: (agent: AgentConnectionInfo) => void): () => void;
    /**
     * Get all connected agents, optionally filtered by location.
     *
     * @param query - Optional filter by context, tabId, frameId
     * @returns Array of connected agent info
     * @throws {LifecycleError} If the store has been destroyed
     *
     * @example
     * const allAgents = store.getAgents();
     * const contentScripts = store.getAgents({ context: 'contentscript' });
     * const tab42Agents = store.getAgents({ tabId: 42 });
     */
    getAgents(query?: Partial<BrowserLocation>): AgentConnectionInfo[];
    /**
     * Destroy the store and clean up all resources.
     * After calling this, the store cannot be used. Use for testing or HMR cleanup.
     *
     * @param options.clearPersisted - If true, also clears persisted storage data
     *
     * @example
     * // In tests
     * afterEach(() => {
     *   store.destroy({ clearPersisted: true });
     * });
     */
    destroy(options?: {
        clearPersisted?: boolean;
    }): void;
    private setupMessageHandlers;
    private setupRpcHandlers;
    private hydrate;
    private notifyStateChange;
    private assertNotDestroyed;
}
/**
 * Create a new Crann store instance.
 *
 * This should be called in your service worker/background script.
 * Each call creates a new, independent store instance (no singleton).
 *
 * @param config - Validated config from createConfig()
 * @param options - Optional store options
 * @param options.debug - Enable debug logging
 * @param options.migrate - Migration function for schema version changes
 * @returns A new Store instance
 *
 * @example
 * // background.ts
 * import { createConfig, createStore } from 'crann';
 *
 * const config = createConfig({
 *   name: 'myFeature',
 *   count: { default: 0, persist: 'local' },
 * });
 *
 * const store = createStore(config, { debug: true });
 *
 * store.subscribe((state, changes) => {
 *   console.log('State changed:', changes);
 * });
 */
export declare function createStore<TConfig extends ConfigSchema>(config: ValidatedConfig<TConfig>, options?: StoreOptions): Store<TConfig>;
