/**
 * RFC 8628 Device Authorization Grant for desktop and CLI apps.
 *
 * Authenticates users via the identity service's device code flow:
 * the app displays a code, the user approves in their browser,
 * and the app receives a workspace-scoped JWT.
 */
import { AmigoError, AuthenticationError } from './errors.js';
export interface DeviceCodeIssuance {
    device_code: string;
    user_code: string;
    verification_uri: string;
    verification_uri_complete: string;
    expires_in: number;
    interval: number;
}
export interface IdentityTokenResponse {
    access_token: string;
    token_type: 'Bearer' | 'DPoP';
    expires_in: number;
    scope: string;
    session_id?: string;
    refresh_token?: string;
}
export interface WorkspaceChoice {
    workspace_id: string;
    role?: string;
    name?: string;
}
export interface MultiWorkspaceResponse {
    error: 'workspace_selection_required';
    workspaces: WorkspaceChoice[];
    access_token?: string;
    token_type?: string;
    expires_in?: number;
    scope?: string;
    refresh_token?: string;
}
export type DeviceCodeStatus = 'authorization_pending' | 'polling' | 'approved' | 'expired' | 'denied' | 'slow_down';
export interface DeviceCodeLoginOptions {
    /** Identity service base URL. Default: https://api.platform.amigo.ai */
    identityBaseUrl?: string;
    /**
     * Workspace this device login targets. Required: the device code is pinned
     * to this workspace at issuance, the browser approver must hold a session
     * scoped to it, and the token returned to the CLI is scoped to it.
     */
    workspaceId: string;
    /** Client description for audit logs */
    clientDescription?: string;
    /** OAuth scope to request */
    scope?: string;
    /** Called when device code is issued — display instructions to user */
    onCode: (issuance: DeviceCodeIssuance) => void | Promise<void>;
    /** Called with polling status updates */
    onStatus?: (status: DeviceCodeStatus) => void;
    /**
     * Fallback workspace picker for legacy / un-pinned device codes only.
     * With `workspaceId` pinned (now required), identity returns a
     * workspace-scoped token directly and this is never invoked.
     * @deprecated Pass `workspaceId`; this will be removed in a future release.
     */
    onWorkspaceRequired?: (workspaces: WorkspaceChoice[]) => Promise<string>;
    /** AbortSignal to cancel the login flow */
    signal?: AbortSignal;
    /** Custom fetch implementation */
    fetch?: typeof globalThis.fetch;
}
export interface AuthResult {
    accessToken: string;
    refreshToken: string;
    workspaceId: string;
    expiresAt: number;
    scope?: string;
}
export interface StoredCredentials {
    access_token: string;
    refresh_token: string;
    workspace_id: string;
    expires_at: number;
    scope?: string;
    identity_base_url?: string;
}
export interface TokenStorage {
    load(): Promise<StoredCredentials | null>;
    save(credentials: StoredCredentials): Promise<void>;
    clear(): Promise<void>;
}
export declare class DeviceCodeExpiredError extends AmigoError {
    constructor(message?: string);
}
export declare class DeviceCodeDeniedError extends AmigoError {
    constructor(message?: string);
}
export declare class RefreshTokenExpiredError extends AuthenticationError {
    constructor(message?: string);
}
export declare class LoginCancelledError extends AmigoError {
    constructor();
}
export declare function decodeJwtPayload(jwt: string): Record<string, unknown> | null;
export declare function loginWithDeviceCode(options: DeviceCodeLoginOptions): Promise<AuthResult>;
export interface TokenManagerConfig {
    storage?: TokenStorage;
    identityBaseUrl?: string;
    fetch?: typeof globalThis.fetch;
}
export declare class TokenManager {
    private readonly _storage;
    private readonly _baseUrl;
    private readonly _fetch;
    private _cached;
    private _refreshPromise;
    constructor(config?: TokenManagerConfig);
    store(result: AuthResult): Promise<void>;
    getAccessToken(): Promise<{
        token: string;
        workspaceId: string;
    } | null>;
    hasCredentials(): Promise<boolean>;
    clear(): Promise<void>;
    private _loadCached;
    private _refresh;
    private _doRefresh;
}
export declare class FileTokenStorage implements TokenStorage {
    private readonly _explicitPath;
    private _resolvedPath;
    constructor(filePath?: string);
    private _filePath;
    load(): Promise<StoredCredentials | null>;
    save(credentials: StoredCredentials): Promise<void>;
    clear(): Promise<void>;
}
export declare class MemoryTokenStorage implements TokenStorage {
    private _credentials;
    load(): Promise<StoredCredentials | null>;
    save(credentials: StoredCredentials): Promise<void>;
    clear(): Promise<void>;
}
export declare function formatDeviceCodeInstructions(issuance: DeviceCodeIssuance): string;
export declare function formatDeviceCodeLink(issuance: DeviceCodeIssuance): string;
export declare function openBrowser(url: string): Promise<boolean>;
export declare function formatWorkspaceList(workspaces: WorkspaceChoice[]): string;
//# sourceMappingURL=device-code.d.ts.map