/** * Bulk delete — purge many sessions from every logged-in server at once. * * Deletion existed only one session at a time (`DELETE /api/conversations/:id`, * and `recall_forget` over MCP). That is fine for "forget that conversation" * and useless for the case that actually produces junk: a tool that fabricates * sessions. A misfiring model-probe wrote 475 one-line transcripts into one * project — 94% of its indexed history — and clearing them meant 475 HTTP * round trips driven by hand. * * ── Why the sync endpoint rather than N deletes ──────────────────────────── * `POST /api/sync { tombstones: [...] }` already purges AND tombstones a whole * array in one request, and it is the same path the collector uses when it * notices a transcript disappeared locally. Reusing it means bulk deletion is * not a second implementation of "remove a session everywhere" that has to stay * in agreement with the first one — it IS the first one, called with more rows. * * ── Resurrection ─────────────────────────────────────────────────────────── * A tombstone is why this sticks. The server records every purged id and the * ingest path skips anything in that set (`deadSet` in routes/sync.ts), so a * later sync — from this machine with a stale ledger, or from a second device * that still has the transcript — cannot put it back. The consequence is worth * stating plainly to the caller: deleting a session whose local transcript * still exists means that transcript can never be indexed again. */ import { type Credentials } from './sync-client.js'; /** Rows as `/api/conversations/recent` returns them. */ export interface SessionRow { sessionId: string; firstPrompt?: string; projectId?: string; tool?: string; } export interface SelectOptions { /** Logical project id, e.g. `git:github.com/me/repo`. */ project?: string; /** Keep only sessions whose first prompt is EXACTLY this, trimmed. */ match?: string; /** Keep only sessions from this tool (claude, codex, …). */ tool?: string; /** Stop after this many matches. */ limit?: number; } export interface DeleteOutcome { requested: number; perTarget: Record; /** Deleted on at least one server. */ deleted: number; } /** Ids per tombstone POST. Large enough to be one request for a typical * cleanup, small enough that a failure loses a bounded amount of work. */ export declare const BATCH = 250; /** * Enumerate the sessions a selector matches, newest first. * * Paging walks the WHOLE project rather than trusting page 0 — the same trap * `/api/data/delete` had to fix: rows come back mtime-ordered, so a filter that * matches only old sessions finds nothing on the first page and would report an * empty selection on a project with thousands of rows. */ export declare function selectSessions(target: Credentials, opts: SelectOptions, fetchImpl?: typeof fetch): Promise; /** * Purge + tombstone `ids` on every logged-in server. * * Per-target failures are recorded, never thrown: with two servers configured, * one being unreachable must not hide that the other succeeded — the caller * has to be able to say which copies are actually gone. */ export declare function bulkDelete(ids: string[], opts?: { targets?: Credentials[]; fetchImpl?: typeof fetch; onProgress?: (done: number, total: number) => void; }): Promise; /** One recorded deletion. */ export interface Tombstone { session_id: string; deleted_at: number; } /** * What has been deleted on a server, newest first. * * A purged session leaves nothing else behind to find it by, so this list is * the only route back from a delete. */ export declare function listTombstones(target: Credentials, limit?: number, fetchImpl?: typeof fetch): Promise<{ total: number; tombstones: Tombstone[]; }>; /** * Lift tombstones so those sessions may be re-uploaded. * * Restores no content by itself — it removes the server's refusal. The * transcript has to still exist on some device, which is why the CLI tells the * caller to re-sync afterwards rather than claiming the data is back. */ export declare function restoreSessions(ids: string[], opts?: { targets?: Credentials[]; fetchImpl?: typeof fetch; }): Promise<{ requested: number; restored: number; perTarget: Record; }>; /** * Does this invocation need an explicit confirmation? * * Only when the caller DID NOT ENUMERATE the set. `delete ` has always * deleted that id immediately and scripts depend on it — the repo's own privacy * E2E calls it non-interactively, and demanding --yes for ids typed on the * command line broke that contract for no safety gain: naming a session IS the * confirmation. * * A selector is different. --project/--match COMPUTE the set, so its size is * discovered rather than intended, and that is where a wrong pattern quietly * takes hundreds with it. --stdin sits in the same bucket: the ids came from * somewhere the person may not have read, and stdin is already a pipe, so there * is nothing left to prompt on. */ export declare function needsConfirmation(opts: { argvIds: number; project?: string; stdin?: boolean; }): boolean; //# sourceMappingURL=bulk-delete.d.ts.map