import type { TeamSendTask } from '../team-send-contract.js'; import { type ArkmeFileOpenResult, type ArkmeFilePolicy, type ArkmeFileProgress, type ArkmeFileReception, type ArkmeFileSendInput, type ArkmeFileSendTask, type ArkmeLocalFile } from '../file-transfer-contract.js'; import type { ArkmeUploadedAsset, ArkmeSourceSendResult } from '../types.js'; type Metadata = Pick; interface StoredFile extends ArkmeLocalFile { sha256: string; createdAtMillis: number; asset?: ArkmeUploadedAsset; retention?: 'references'; longArticle?: true; } export type FileTransferSendOutcome = { kind: 'owner_accepted'; result: ArkmeSourceSendResult; } | { kind: 'owner_not_accepted'; message: string; code?: string; retryable?: boolean; } | { kind: 'owner_outcome_unknown'; message?: string; code?: string; }; export interface FileTransferPorts { currentUser(): Promise; retainedFileRefs?(userId: number): Promise; validateSource(sourceRef: string): Promise; upload(path: string, metadata: StoredFile, progress: (value: ArkmeFileProgress) => void, userId: number, signal: AbortSignal): Promise; send(input: ArkmeFileSendInput, assets: ArkmeUploadedAsset[], backgroundSound: import('../types.js').ArkmeRichBackgroundSoundInput | undefined, userId: number, signal: AbortSignal): Promise; fetchMedia(ref: string, signal: AbortSignal): Promise<{ response: Response; descriptor: Metadata; }>; openPath?(path: string, signal: AbortSignal): Promise; reconcile?(input: ArkmeFileSendInput, signal: AbortSignal): Promise; } /** Plugin-owned files, not DSH session attachments. No client-controlled path is persisted. */ export declare class FileTransfers { private readonly directory; private readonly ports; private readonly states; private writes; private mutations; private directUploads; private readonly uploadingRefs; private queue; private readonly jobs; private readonly controllers; private readonly receptions; private readonly policy; constructor(directory: string, ports: FileTransferPorts, maxBytes: number); capabilities(): ArkmeFilePolicy; cancelActive(): void; settled(): Promise; private root; private path; private openDirectory; private nativeOpenPath; private assertUser; private state; private save; private exclusive; private validateMetadata; stageLongArticleImage(temporaryPath: string, metadata: Metadata, expectedUserId?: number): Promise; stage(temporaryPath: string, metadata: Metadata, expectedUserId?: number, retention?: 'references'): Promise; private stageLocal; private prune; /** Validate new references and persist their owner without a cleanup/removal gap. Local I/O only. */ withReferences(refs: readonly string[], userId: number, persist: () => Promise): Promise; readLocal(ref: string): Promise<{ path: string; file: ArkmeLocalFile; }>; openLocal(ref: string, signal?: AbortSignal): Promise; openLocalFolder(ref: string, signal?: AbortSignal): Promise<{ folderOpened: true; }>; private openLocalTarget; files(): Promise; remove(ref: string): Promise; tasks(sourceRef?: string): Promise; /** Internal Team delivery uses the existing account store and file-reference lock. */ teamSends(userId: number): Promise; mutateTeamSends(userId: number, mutate: (tasks: TeamSendTask[]) => void): Promise; stageBytes(contentBase64: string, metadata: Omit): Promise; discard(taskRef: string): Promise; reconcile(taskRef: string): Promise; enqueue(input: ArkmeFileSendInput): Promise; private imageFailure; uploadLongArticleImages(fileRefs: readonly string[], signal?: AbortSignal): Promise; uploadRefs(fileRefs: readonly string[], signal?: AbortSignal, progress?: (ref: string, value: ArkmeFileProgress) => void): Promise; private uploadDirectRefs; retry(taskRef: string): Promise; private schedule; reception(mediaRef: string, start?: boolean): Promise; } export {}; //# sourceMappingURL=file-transfers.d.ts.map