/**
 * @bobfrankston/mailx-settings
 * Settings management with shared/local split.
 *
 * Files (shared — on OneDrive or similar):
 *   accounts.jsonc    — IMAP/SMTP account configs
 *   preferences.jsonc — UI, sync, font settings
 *   allowlist.jsonc   — remote content allow-list
 *
 * Local overrides (~/.mailx/):
 *   config.jsonc      — pointer to shared dir + local-only settings (storePath, historyDays)
 *   accounts.jsonc    — cached copy, fallback when shared unavailable
 *   preferences.jsonc — local overrides merged on top of shared
 *   allowlist.jsonc   — cached copy
 *
 * The old settings.jsonc is still supported for backward compatibility.
 */
import type { MailxSettings, AccountConfig, AutocompleteSettings, AiKeys } from "@bobfrankston/mailx-types";
declare const LOCAL_DIR: string;
/** Subscribers notified whenever lastCloudError changes (push to UI immediately). */
type CloudErrorListener = (error: string | null, context?: {
    op: "read" | "write";
    filename: string;
}) => void;
export declare function onCloudError(cb: CloudErrorListener): () => void;
export declare function getLastCloudError(): string | null;
declare function getSharedDir(): string;
/** Read a file via cloud API (when filesystem mount not available) */
export declare function cloudRead(filename: string): Promise<string | null>;
/** Read a file from the shared cloud config folder as raw bytes, base64-encoded.
 *  Binary-safe sibling of cloudRead — used for the optional custom reminder
 *  sound that lives next to the JSONC config on Drive. Returns null if cloud
 *  isn't configured, the file is missing, or the read errors (caller falls back
 *  to the built-in chime). */
export declare function cloudReadBinary(filename: string): Promise<string | null>;
/** Write a file via cloud API. Throws on failure with a descriptive error,
 *  and updates lastCloudError so UI banners pick it up via getStorageInfo()
 *  and the onCloudError listener. */
export declare function cloudWrite(filename: string, content: string): Promise<void>;
/** Whether cloud API fallback is active */
export declare function isCloudMode(): boolean;
/** Get storage provider info for display */
export declare function getStorageInfo(): {
    provider: string;
    mode: "mount" | "api" | "local";
    cloudPath?: string;
    folderName?: string;
    folderId?: string;
    configDir?: string;
    cloudError?: string;
};
export interface ProviderDefaults {
    label: string;
    imap: {
        host: string;
        port: number;
        tls: boolean;
        auth: "password" | "oauth2";
    };
    smtp: {
        host: string;
        port: number;
        tls: boolean;
        auth: "password" | "oauth2";
    };
}
/** Single source of truth for provider IMAP/SMTP defaults by email domain.
 *  desktop setup (`detectEmailProvider`) and ANY other setup path must use THIS,
 *  not a private re-listing — `detectEmailProvider` only knew Gmail+Outlook, so
 *  AOL/Yahoo/iCloud never auto-configured (Bob 2026-06-19, economy of mechanism /
 *  "prefer Drive with local caching should be a shared component"). */
export declare function providerForDomain(domain: string): ProviderDefaults | undefined;
/** Canonical form of an email address — applies provider-specific
 *  equivalences so two superficially-different strings that resolve to the
 *  SAME mailbox produce the same canonical key. Today: Gmail (and
 *  googlemail.com) ignores dots in the local-part and treats everything
 *  from `+` onward as a tag — `Bob.Frankston+work@Gmail.com`,
 *  `bobfrankston@gmail.com`, and `BOBFRANKSTON@GOOGLEMAIL.COM` all collapse
 *  to `bobfrankston@gmail.com`. Other domains: lowercase only. Used by the
 *  OAuth token cache so a Gmail account doesn't end up with two parallel
 *  token directories (one with dots, one without) racing each other and
 *  triggering full reauth (Bob 2026-05-25).
 *
 *  Output is suitable for direct comparison; for filesystem dir names use
 *  `tokenDirName(email)` which applies the `[@.]/_` sanitization on top. */
export declare function canonicalEmail(email: string): string;
/** Compute the OAuth token-cache directory name for an email address.
 *  Canonicalizes first (so Gmail dot/`+tag`/case variants share one dir),
 *  then sanitizes `@`/`.` to `_`. Use everywhere a token cache path is
 *  derived from an email so all code paths land on the same directory. */
export declare function tokenDirName(email: string): string;
/** Fill in provider defaults for an account based on email domain.
 *  Exported so mailx-service's leanAccountsJsonc helper can reuse the same
 *  canonicalization rules that loadAccounts uses. */
export declare function normalizeAccount(acct: any, globalName?: string, globalSig?: any, globalSignature?: string): AccountConfig;
declare const DEFAULT_PREFERENCES: {
    ui: {
        theme: "system" | "dark" | "light";
        editor: "quill" | "tiptap";
        folderWidth: number;
        listViewerSplit: number;
        fontSize: number;
    };
    sync: {
        intervalMinutes: number;
        historyDays: number;
        prefetch: boolean;
    };
    reminders: {
        sound: string;
    };
    autocomplete: {
        enabled: boolean;
        provider: "ollama";
        ollamaUrl: string;
        ollamaModel: string;
        cloudApiKey: string;
        cloudModel: string;
        debounceMs: number;
        maxTokens: number;
    };
};
declare const DEFAULT_AUTOCOMPLETE: AutocompleteSettings;
declare const DEFAULT_ALLOWLIST: {
    senders: string[];
    domains: string[];
    recipients: string[];
    flaggedSenders: string[];
    flaggedDomains: string[];
};
/** Load account configs */
export declare function loadAccounts(): AccountConfig[];
/** Load accounts, preferring the cloud copy when cloud is configured.
 *  The local file in `~/.rmfmail/` is an offline cache, NOT the source of
 *  truth — earlier versions returned the local copy whenever it was non-empty,
 *  which left the desktop reading a stale single-account file forever after
 *  the GDrive folder lookup got fixed. */
export declare function loadAccountsAsync(): Promise<AccountConfig[]>;
/** Strip default-valued fields from a normalized AccountConfig so the
 *  serialized JSONC stays compact and human-editable. The previous version
 *  was round-tripping every defaulted field (port: 993, tls: true, auth:
 *  "password", enabled: true, etc.), which bloated a 10-line accounts.jsonc
 *  to 60+ lines and embedded unnecessary "knowledge" about defaults.
 *
 *  Rules:
 *  - Drop fields that match the provider default (host/port/tls/auth derived
 *    from email domain via PROVIDERS).
 *  - Drop `enabled: true` (default).
 *  - Drop `name` if equal to the file-level `globalName`.
 *  - Drop `imap.user` / `smtp.user` if they equal the email.
 *  - Drop `sig.html: false` (default; only keep when user enabled HTML sigs).
 *  - Keep field order: id → label → email → primary* → imap → smtp → defaultSend
 *    → relayDomains → identityDomains → syncContacts → sig.
 *    Curated for readability, not alphabetic. */
export declare function denormalizeAccount(acct: AccountConfig, globalName?: string): any;
/** Save account configs */
/** Save accounts — merges with cloud copy by email (multi-client safe).
 *  Writes the lean form via denormalizeAccount so accounts.jsonc stays
 *  compact and human-editable. Preserves the top-level `keys` field
 *  (AI API keys) if present in the existing cloud or local file. */
export declare function saveAccounts(accounts: AccountConfig[]): Promise<void>;
/** Load top-level AI keys from accounts.jsonc. Returns empty placeholders
 *  ({ anthropic: "", openai: "" }) when the file lacks a `keys` section,
 *  so callers can call this unconditionally without missing-section guards.
 *  Reads from the same shared/local path resolution as loadAccounts. */
export declare function loadKeys(): AiKeys;
/** Save AI keys back to accounts.jsonc, preserving the rest of the file
 *  (accounts list, file-level name). Used by Settings → AI to persist a
 *  key the user just entered. Cloud-synced via saveFile. */
export declare function saveKeys(keys: AiKeys): Promise<void>;
/** First-run helper: ensure `keys: { anthropic: "", openai: "" }` is
 *  materialized in accounts.jsonc so the user sees placeholders for every
 *  supported provider when they open the config editor. Adds missing
 *  fields without disturbing existing values, so `keys: {}` becomes
 *  `keys: { anthropic: "", openai: "" }` and `keys: { anthropic: "sk-..." }`
 *  becomes `keys: { anthropic: "sk-...", openai: "" }`. Idempotent. */
export declare function ensureKeysSectionExists(): Promise<void>;
/** First-run helper: write a `groups` sample into contacts.jsonc so the
 *  user sees how to set up a mailing list. Compose's `expandRecipients`
 *  loads `cfg.groups` from this file at send time and resolves group
 *  names to the member addresses. Idempotent — only writes if `groups`
 *  is missing entirely (won't clobber a user-defined map). The sample
 *  uses example.com so it's harmless if the user accidentally sends to
 *  the unmodified placeholder. */
export declare function ensureGroupsSampleExists(): Promise<void>;
/** First-run helper: materialize the `autocomplete` block in
 *  preferences.jsonc with explicit defaults. loadPreferences() merges
 *  defaults at read time, but the file on disk often has no
 *  `autocomplete` key, so a user opening Settings → Edit config files
 *  doesn't see the AI provider knobs. This writes the defaults out so
 *  the user can edit them. Idempotent. */
export declare function ensureAutocompletePrefsExist(): Promise<void>;
/** Load preferences (shared + local overrides, with legacy fallback) */
export declare function loadPreferences(): typeof DEFAULT_PREFERENCES;
/** Save preferences */
export declare function savePreferences(prefs: any): void;
/** Load autocomplete settings */
export declare function loadAutocomplete(): AutocompleteSettings;
/** Save autocomplete settings */
export declare function saveAutocomplete(settings: AutocompleteSettings): void;
/** Load remote content allow-list (sync — local/shared filesystem only) */
export declare function loadAllowlist(): typeof DEFAULT_ALLOWLIST;
/** Load the allow-list, cloud-canonical. Mirrors loadAccountsAsync: when a
 *  cloud provider is configured (drive.file scope — no filesystem mount), the
 *  Drive copy is authoritative and cloudRead() caches it to LOCAL_DIR so the
 *  sync loadAllowlist() picks it up afterward. Without this, a fresh install
 *  never pulls the shared allowlist.jsonc and falls back to DEFAULT_ALLOWLIST. */
export declare function loadAllowlistAsync(): Promise<typeof DEFAULT_ALLOWLIST>;
/** Save allow-list — merges with existing cloud copy (multi-client safe) */
export declare function saveAllowlist(list: typeof DEFAULT_ALLOWLIST): Promise<void>;
/** Load user-added dictionary words. Mirrored to GDrive so "Add to dictionary"
 *  on one machine appears on every machine. Returns a deduped string array.
 *  Tries the cloud copy first (so a fresh machine sees prior words), then
 *  the local cache. Empty array when nothing has been saved yet. */
export declare function loadUserDict(): Promise<string[]>;
/** Save user dictionary — merges with the cloud copy so concurrent edits on
 *  different machines union rather than overwrite. */
export declare function saveUserDict(words: string[]): Promise<void>;
/** Load settings — unified view combining all files (backward compatible) */
export declare function loadSettings(): MailxSettings;
export declare function saveSettings(settings: MailxSettings): Promise<void>;
/** Get the local store base path */
export declare function getStorePath(): string;
/** Get the local data directory (DB, store, etc.) */
export declare function getConfigDir(): string;
/** Get the shared settings directory */
export { getSharedDir };
/** Initialize local config if it doesn't exist */
export declare function initLocalConfig(sharedDir?: string, storePath?: string): void;
/** Initialize config with Google Drive cloud storage.
 *  Finds or creates the app-owned ".rmfmail" folder via Drive API and stores its ID.
 *  No mount scanning — API only. Existing settings at other paths (e.g., home/.rmfmail
 *  from Desktop sync) must be migrated manually or via config.jsonc importPath. */
export declare function initCloudConfig(provider?: "gdrive" | "onedrive"): Promise<void>;
declare const DEFAULT_SETTINGS: MailxSettings;
/** Get historyDays for an account: per-account override > system override > shared default */
export declare function getHistoryDays(accountId?: string): number;
/** Get prefetch setting: download bodies during sync (default true) */
export declare function getPrefetch(): boolean;
export { DEFAULT_SETTINGS, DEFAULT_ALLOWLIST, DEFAULT_PREFERENCES, DEFAULT_AUTOCOMPLETE, LOCAL_DIR };
/** Deploy the app-owned `.md` reference docs to the shared cloud folder so
 *  users can read them next to the `.jsonc` files they document. The .md
 *  files live in the app bundle (`<workspace>/app/docs/` in dev, or
 *  `<package>/docs/` in published builds) and are overwritten on every
 *  release — the file header documents that fact, so users know not to
 *  edit them.
 *
 *  Skip-path: a manifest file `.docs-version` on the cloud records the
 *  app version that last deployed. We re-deploy only when the running
 *  app's version differs, so startup doesn't pound Drive on every launch.
 *
 *  This function is fire-and-forget at the call site; failures are logged
 *  but never throw. The `.md` files are reference material, not load-
 *  bearing — the app works without them.
 */
export declare function deployDocs(appVersion: string): Promise<void>;
//# sourceMappingURL=index.d.ts.map