interface ExchangeResponse { api_key: string; user: { id: string; githubUsername: string; email: string; }; repository?: { owner: string; name: string; }; githubAppInstallUrl?: string | null; } /** * The server rejected the token exchange because the GitHub token cannot see * the target repository. Login uses the GitHub App Device Flow, so the token * is user-to-server and only sees repositories covered by an App * installation — for a repo the user owns, this almost always means the App * simply isn't installed on it. Carries the install URL the server returned * so the login flow can walk the user through installing and then resume. */ export declare class RepoNotFoundError extends Error { readonly installUrl: string | null; constructor(message: string, installUrl: string | null); } /** * Execute the unified login flow for hub-launch * * This command authenticates the user with both GitHub and hula-project in one flow: * 1. Initiates GitHub App Device Flow * 2. User authorizes in browser * 3. Receives GitHub token * 4. Exchanges token for hula-project API key * 5. Configures gh CLI with GitHub token * 6. Saves API key to config */ export declare function executeLogin(config: any): Promise; /** * Handle a repo_not_found exchange failure: explain that the GitHub App * isn't installed on the repository, open the install page in the browser, * then poll the exchange until the installation makes the repo visible. * Mirrors the device-flow polling pattern used for the GitHub token itself. * * Exported for tests; production code injects the real exchange call. */ export declare function promptInstallAndRetryExchange(error: RepoNotFoundError, repository: { owner: string; repo: string; }, retryExchange: () => Promise, pollIntervalMs?: number, timeoutMs?: number): Promise; /** * Load saved GitHub token metadata */ export declare function loadGitHubToken(): Promise<{ access_token: string; refresh_token?: string; expires_at?: string; } | null>; /** * Check if token is expired or will expire soon */ export declare function isTokenExpired(expiresAt?: string): boolean; /** * Check if a token will expire within the given time window. * Returns false if no expiry info is available (non-expiring token). * @param expiresAt - ISO 8601 expiry timestamp, or null/undefined if no expiry * @param bufferMs - Window in milliseconds (e.g., 2 * 60 * 60 * 1000 for 2 hours) */ export declare function isTokenExpiringWithin(expiresAt: string | null | undefined, bufferMs: number): boolean; /** * Refresh GitHub token using refresh_token */ export declare function refreshGitHubToken(refreshToken: string, config: any): Promise<{ access_token: string; refresh_token?: string; expires_in?: number; } | null>; export {}; //# sourceMappingURL=login.d.ts.map