import type { AttachmentInput } from "@stigmer/sdk";
/**
 * Lifecycle phase of a single attachment managed by {@link useAttachments}.
 *
 * - `uploading` — bytes are being sent to the server
 * - `ready` — upload succeeded, `storageKey` is available
 * - `error` — upload failed, `error` describes the failure
 */
export type AttachmentPhase = "uploading" | "ready" | "error";
/**
 * State for a single file being managed by the hook.
 *
 * The `id` is a stable string generated at add-time, used as a React
 * key and for removal. The same `File` added twice produces two
 * independent entries with distinct IDs.
 *
 * @example
 * ```tsx
 * const attachments = useAttachments();
 *
 * attachments.entries.map((entry) => (
 *   <span key={entry.id}>
 *     {entry.file.name}
 *     {entry.phase === "uploading" && <Spinner />}
 *     {entry.phase === "error" && <span>{entry.error}</span>}
 *     {entry.phase === "ready" && <CheckIcon />}
 *   </span>
 * ));
 * ```
 */
export interface AttachmentEntry {
    /** Unique client-side identifier for this attachment. */
    readonly id: string;
    /** The original `File` object selected by the user. */
    readonly file: File;
    /** Current upload lifecycle phase. */
    readonly phase: AttachmentPhase;
    /** MIME type of the file (e.g. `"image/png"`). */
    readonly contentType: string;
    /** Server-assigned storage key. Set when `phase` is `"ready"`. */
    readonly storageKey: string | null;
    /** Human-readable error message. Set when `phase` is `"error"`. */
    readonly error: string | null;
}
/** Options for {@link useAttachments}. */
export interface UseAttachmentsOptions {
    /**
     * Called when a file is rejected during `addFiles` (e.g., exceeds
     * the size limit). Consumers can use this for toast notifications.
     */
    readonly onValidationError?: (message: string) => void;
}
/** Return value of {@link useAttachments}. */
export interface UseAttachmentsReturn {
    /** Current attachment entries (uploading, ready, or errored). */
    readonly entries: readonly AttachmentEntry[];
    /** True when at least one entry is in the `"uploading"` phase. */
    readonly isUploading: boolean;
    /** Number of entries that are ready for submission. */
    readonly readyCount: number;
    /** True when there are entries and all are ready (none uploading or errored). */
    readonly allReady: boolean;
    /** True when there is at least one entry (in any phase). */
    readonly hasEntries: boolean;
    /**
     * Add one or more files. Each file is validated and uploaded
     * immediately. Invalid files (e.g., too large) are rejected via
     * `onValidationError` and not added.
     */
    readonly addFiles: (files: FileList | File[]) => void;
    /** Remove an entry by its stable ID. Aborts in-flight uploads. */
    readonly removeEntry: (id: string) => void;
    /** Retry a failed upload. */
    readonly retryEntry: (id: string) => void;
    /** Clear all entries and abort any in-flight uploads. */
    readonly clear: () => void;
    /**
     * Produces the `AttachmentInput[]` suitable for execution creation.
     * Only includes entries in the `"ready"` phase.
     */
    readonly toAttachmentInputs: () => AttachmentInput[];
}
/**
 * Behavior hook that manages file attachments for agent executions.
 *
 * Handles the full lifecycle: file validation, upload via
 * `stigmer.agentExecution.uploadAttachment()`, progress tracking,
 * error handling, and retry. Produces `AttachmentInput[]` ready
 * for execution creation.
 *
 * Files are uploaded immediately on selection so the `storageKey`
 * is available by the time the user submits their message.
 *
 * Platform builders who want custom attachment UI import this hook
 * directly. The {@link SessionComposer} styled component uses it
 * internally.
 *
 * @example
 * ```tsx
 * function CustomComposer() {
 *   const attachments = useAttachments({
 *     onValidationError: (msg) => toast.error(msg),
 *   });
 *
 *   return (
 *     <div>
 *       <input
 *         type="file"
 *         multiple
 *         onChange={(e) => {
 *           if (e.target.files) attachments.addFiles(e.target.files);
 *         }}
 *       />
 *       {attachments.entries.map((entry) => (
 *         <div key={entry.id}>
 *           {entry.file.name} — {entry.phase}
 *           {entry.phase === "error" && (
 *             <button onClick={() => attachments.retryEntry(entry.id)}>
 *               Retry
 *             </button>
 *           )}
 *           <button onClick={() => attachments.removeEntry(entry.id)}>
 *             Remove
 *           </button>
 *         </div>
 *       ))}
 *     </div>
 *   );
 * }
 * ```
 */
export declare function useAttachments(options?: UseAttachmentsOptions): UseAttachmentsReturn;
//# sourceMappingURL=useAttachments.d.ts.map