import { type CooldownReason, type RateLimitStateV3, type AccountMetadataV1, type AccountStorageV1, type AccountMetadataV3, type AccountStorageV3 } from "./storage/migrations.js"; export type { CooldownReason, RateLimitStateV3, AccountMetadataV1, AccountStorageV1, AccountMetadataV3, AccountStorageV3 }; export interface FlaggedAccountMetadataV1 extends AccountMetadataV3 { flaggedAt: number; flaggedReason?: string; lastError?: string; } export interface FlaggedAccountStorageV1 { version: 1; accounts: FlaggedAccountMetadataV1[]; } export declare function getWorkspaceIdentityKey(account: { organizationId?: string; accountId?: string; refreshToken: string; }): string; export type ImportBackupMode = "none" | "best-effort" | "required"; export interface ImportAccountsOptions { /** * Optional prefix used for pre-import backup file names. * Only applied when backupMode is not "none". */ preImportBackupPrefix?: string; /** * Backup policy before import apply: * - none: do not create a pre-import backup * - best-effort: attempt backup, continue on failure * - required: backup must succeed or import aborts */ backupMode?: ImportBackupMode; } export type ImportBackupStatus = "created" | "skipped" | "failed"; export interface ImportAccountsResult { imported: number; total: number; skipped: number; backupStatus: ImportBackupStatus; backupPath?: string; backupError?: string; } export interface ImportPreviewResult { imported: number; total: number; skipped: number; } /** * Custom error class for storage operations with platform-aware hints. */ export declare class StorageError extends Error { readonly code: string; readonly path: string; readonly hint: string; constructor(message: string, code: string, path: string, hint: string, cause?: Error); } /** * Generate platform-aware troubleshooting hint based on error code. */ export declare function formatStorageErrorHint(error: unknown, path: string): string; export declare function setStoragePath(projectPath: string | null): void; export declare function setStoragePathDirect(path: string | null): void; /** * Returns the file path for the account storage JSON file. * @returns Absolute path to the accounts.json file */ export declare function getStoragePath(): string; export declare function getFlaggedAccountsPath(): string; /** * Removes duplicate accounts, keeping the most recently used entry for each unique key. * Deduplication identity hierarchy: organizationId -> accountId -> refreshToken. * @param accounts - Array of accounts to deduplicate * @returns New array with duplicates removed */ export declare function deduplicateAccounts(accounts: T[]): T[]; /** * Removes duplicate legacy accounts by email, keeping the most recently used entry. * Accounts with organizationId/accountId are never merged by email to avoid collapsing workspace variants. * Accounts without email are always preserved. * @param accounts - Array of accounts to deduplicate * @returns New array with email duplicates removed */ export declare function deduplicateAccountsByEmail(accounts: T[]): T[]; /** * Normalizes and validates account storage data, migrating from v1 to v3 if needed. * Handles deduplication, index clamping, and per-family active index mapping. * @param data - Raw storage data (unknown format) * @returns Normalized AccountStorageV3 or null if invalid */ export declare function normalizeAccountStorage(data: unknown): AccountStorageV3 | null; /** * Loads OAuth accounts from disk storage. * Automatically migrates v1 storage to v3 format if needed. * @returns AccountStorageV3 if file exists and is valid, null otherwise */ export declare function loadAccounts(): Promise; /** * Executes a read-modify-write transaction under the storage lock and exposes * an unlocked persist callback so nested save operations do not deadlock. */ export declare function withAccountStorageTransaction(handler: (current: AccountStorageV3 | null, persist: (storage: AccountStorageV3) => Promise) => Promise): Promise; /** * Persists account storage to disk using atomic write (temp file + rename). * Creates the .opencode directory if it doesn't exist. * Verifies file was written correctly and provides detailed error messages. * @param storage - Account storage data to save * @throws StorageError with platform-aware hints on failure */ export declare function saveAccounts(storage: AccountStorageV3): Promise; /** * Deletes the account storage file from disk. * Silently ignores if file doesn't exist. */ export declare function clearAccounts(): Promise; export declare function loadFlaggedAccounts(): Promise; /** * Executes a read-modify-write transaction for flagged account storage under the * shared storage lock so concurrent callers cannot lose updates. */ export declare function withFlaggedAccountStorageTransaction(handler: (current: FlaggedAccountStorageV1, persist: (storage: FlaggedAccountStorageV1) => Promise) => Promise): Promise; export declare function saveFlaggedAccounts(storage: FlaggedAccountStorageV1): Promise; export declare function clearFlaggedAccounts(): Promise; export declare function createTimestampedBackupPath(prefix?: string): string; /** * Import preview/apply analysis is pure in-memory work: it does not touch disk * and it does not log token or workspace values. The surrounding * `withAccountStorageTransaction` caller keeps Windows lock-retry and * serialized read-modify-write behavior; see `test/storage.test.ts` for the * overlapping transaction regression and pre-import backup lock coverage. */ export declare function previewImportAccounts(filePath: string): Promise; /** * Exports current accounts to a JSON file for backup/migration. * @param filePath - Destination file path * @param force - If true, overwrite existing file (default: true) * @throws Error if file exists and force is false, or if no accounts to export */ export declare function exportAccounts(filePath: string, force?: boolean): Promise; /** * Imports accounts from a JSON file, merging with existing accounts. * Deduplicates by identity key first (organizationId -> accountId -> refreshToken), * then applies legacy email dedupe only to entries without organizationId/accountId. * @param filePath - Source file path * @throws Error if file is invalid or would exceed MAX_ACCOUNTS */ export declare function importAccounts(filePath: string, options?: ImportAccountsOptions): Promise; //# sourceMappingURL=storage.d.ts.map