import type { AllowedUsers } from "../whitelist.js"; /** * Downloads the Telegram file_id to destPath. * Production default: transport.downloadDocument (grammy wired in bot.ts). * Tests: spy that records calls without any network or disk access. */ export type DownloadFn = (fileId: string, destPath: string) => Promise; /** * Hands a LOCAL file path to the existing src/medical ingest path. * Returns a NON-SENSITIVE count — never marker values/names (nonGoal #3). * Production default: defaultMedicalIngest (execa subprocess below). * Tests: spy that returns fixture counts without spawning any subprocess. */ export type MedicalIngest = (filePath: string) => Promise<{ recordsParsed: number; newRows: number; }>; /** * In-memory stash of pending upload confirmations keyed by uploadId. * Created in the loop, cleared on restart, never written to disk. * * bober: single-process map; extend to a shared Redis key-value store if the bot * runs across multiple processes (low-probability at current scale). */ export type PendingUpload = { fileId: string; fileName: string; chatId: number; }; export type PendingUploadState = Map; export declare function createPendingUploadState(): PendingUploadState; /** * The LOCAL medical ingest destination disclosed to the user BEFORE confirmation. * Named as a constant so unit tests can assert it is present in the prompt text * without hardcoding the exact string in both the handler and the test. */ export declare const LOCAL_INGEST_DEST = ".bober/medical (local health store)"; /** * Build the per-upload opt-in prompt that is shown BEFORE any download. * Must name the local ingest destination and disclose the non-E2E nature of Telegram * so consent is fully informed (sc-5-5). */ export declare function buildUploadPrompt(fileName: string): string; /** * Called when a document message arrives from a whitelisted user. * Stashes the upload in the ephemeral pending map and returns the opt-in prompt. * The file is NOT downloaded at this point — download happens only after Yes (sc-5-2). */ export declare function registerUpload(args: { uploadId: string; chatId: number; fileId: string; fileName: string; pending: PendingUploadState; }): { reply: string; }; /** * Handle a Yes (confirm) or No (cancel) button tap for a pending upload. * * On Yes (confirm): * 1. Look up the stash; consume it (single-shot). * 2. Download the file to a temporary directory via the injected download fn. * 3. Pass the local path to the injected ingest fn exactly once. * 4. Reply with a NON-SENSITIVE count only — never marker values/names (sc-5-5, nonGoal #3). * 5. Remove the temp directory in a finally block (nonGoal #4). * * On No (cancel) or missing stash: * - Ingest fn is NEVER called (sc-5-4). * - Download fn is NEVER called. * - Any ephemeral stash entry is discarded. * * Whitelist re-check on the callback sender id (mirror approvals.ts:63-66, sc-4-5 analog). */ export declare function handleUploadCallback(args: { senderId: number; allowed: AllowedUsers; data: string; pending: PendingUploadState; download: DownloadFn; ingest: MedicalIngest; }): Promise<{ reply: string | null; answer: string; }>; /** * Production MedicalIngest — invokes `agent-bober medical import ` in a * subprocess via execa. The subprocess runs the full medical pipeline including all * EgressGuard / ConsentGate / AuditLog guardrails, keeping them authoritative in the * child process (nonGoal #5). This mirrors defaultPrioritize in prioritize.ts. * * Parses the non-sensitive count from stdout: * records parsed: * new rows: * (see src/cli/commands/medical.ts:255-257 for the exact format) * * bober: one child process per upload confirmation; swap for in-process * IngestionNormalizer.importFile() if subprocess startup latency * exceeds acceptable Telegram response time under load. */ export declare function defaultMedicalIngest(filePath: string): Promise<{ recordsParsed: number; newRows: number; }>; //# sourceMappingURL=upload.d.ts.map