// --------------------------------------------------------------------------- // GENERATED FILE — DO NOT EDIT. // // Source: contracts/schema/** // Generator: contracts/codegen/gen_ts.py // Contract: v1.2.0 // // Hand-editing this file is a merge blocker. Fix the schema and regenerate: // python3 contracts/codegen/gen_ts.py // Only lane PROTO commits to contracts/. // --------------------------------------------------------------------------- import type { BulkTaskResult, CaptureGetRulesParams, CaptureOfferParams, CaptureOfferResult, CaptureRules, CategoryListParams, CategoryListResult, CategoryRemoveParams, CategoryRemoveResult, CategoryUpsertParams, CategoryUpsertResult, DownloadAddBatchParams, DownloadAddBatchResult, DownloadAddResult, DownloadCancelParams, DownloadGetParams, DownloadListParams, DownloadListResult, DownloadPauseParams, DownloadProbeParams, DownloadProbeResult, DownloadProvideAuthParams, DownloadProvideAuthResult, DownloadRefreshUrlParams, DownloadRefreshUrlResult, DownloadRemoveParams, DownloadRemoveResult, DownloadResumeParams, DownloadSpec, DownloadStartParams, DownloadUpdateParams, GrabberHarvestParams, GrabberHarvestResult, GrabberStartParams, GrabberStartResult, GrabberStatusParams, GrabberStatusResult, Limiter, LimiterGetParams, MediaAddVariantParams, MediaAddVariantResult, MediaListVariantsParams, MediaListVariantsResult, QueueListParams, QueueListResult, QueueReorderParams, QueueReorderResult, QueueStartParams, QueueStartResult, QueueStopParams, QueueStopResult, QueueUpsertParams, QueueUpsertResult, RulesListParams, RulesListResult, RulesUpsertParams, RulesUpsertResult, ScheduleGetParams, ScheduleGetResult, ScheduleSetParams, ScheduleSetResult, SessionHelloParams, SessionHelloResult, SessionPairParams, SessionPairResult, SessionSubscribeParams, SessionSubscribeResult, SettingsGetParams, SettingsGetResult, SettingsSetParams, SettingsSetResult, TaskDetail, TaskSummary, } from './types.js'; /** Params and result for every method, keyed by its wire name. */ export interface MethodMap { /** * The daemon's capture policy, so the extension's shouldCapture decision cannot drift from * the daemon's. Fetched on connect and whenever event.settings.changed names a capture.* * key. If this call fails the extension keeps its last known rules and stays fail-open. */ "capture.getRules": { params: CaptureGetRulesParams; result: CaptureRules }; /** * Firefox offers an intercepted response to the daemon. The daemon MUST reply within 750 * ms; the extension abandons the offer and lets Firefox download normally on timeout. This * deadline is the whole reason capture fails open, and it is conformance-tested: a daemon * that is slow, down, or erroring must never cost the user a download. */ "capture.offer": { params: CaptureOfferParams; result: CaptureOfferResult }; /** * Every category with its folder and extension list. The extension calls this to populate * its default-category picker, which is why it is not privileged; it is read-only and * exposes only paths the user already configured. */ "category.list": { params: CategoryListParams; result: CategoryListResult }; /** * Delete a user-created category. Built-in categories are refused with -32602. Tasks filed * under it are reassigned to reassignTo, or to the default category when that is null; no * task is ever orphaned. */ "category.remove": { params: CategoryRemoveParams; result: CategoryRemoveResult }; /** * Create or replace a category. Omit categoryId to create; supply it to replace. Changing * saveDir does not move existing files — the GUI asks separately and issues * download.update per task, so a re-point is never a surprise mass file move. */ "category.upsert": { params: CategoryUpsertParams; result: CategoryUpsertResult }; /** * Create one task. saveDir is canonicalized and checked against saveTo.allowedRoots before * anything is written; a path that escapes them is refused with -32011 and no file is * created. */ "download.add": { params: DownloadSpec; result: DownloadAddResult }; /** * Create many tasks in one call: the clipboard blob, the wildcard expander, and the * extension's 'Download all links'. Partial success is normal and is reported per item * rather than failing the whole batch. */ "download.addBatch": { params: DownloadAddBatchParams; result: DownloadAddBatchResult }; /** * Stop the given tasks and mark them cancelled. The .veloxpart file is kept so the user * can still resume from the list; download.remove is what deletes bytes. */ "download.cancel": { params: DownloadCancelParams; result: BulkTaskResult }; /** * Full detail for one task, including per-segment state. Backs the progress dialog. Poll * it no faster than the progress dialog repaints; the table must use events instead. */ "download.get": { params: DownloadGetParams; result: TaskDetail }; /** * The main table. Filtering, sorting and paging all happen in the daemon so the GUI never * materializes 100k rows to show 40. Called once on connect; after that the table is * maintained from events, never re-fetched on a progress tick. */ "download.list": { params: DownloadListParams; result: DownloadListResult }; /** * Suspend transfers and flush every segment's progress to the .veloxpart.meta file, so a * pause is indistinguishable from a crash as far as resume is concerned. Never loses bytes * already written. */ "download.pause": { params: DownloadPauseParams; result: BulkTaskResult }; /** * Ask what is at a URL without creating a task. Populates the File Info dialog. Runs a * HEAD, falling back to a ranged GET when HEAD is refused, which is also how resumability * is established. Never blocks the RPC loop; the dialog opens immediately and fills in * when this lands. */ "download.probe": { params: DownloadProbeParams; result: DownloadProbeResult }; /** * Answer an event.auth.required challenge. The task sits in retry_wait until this arrives; * on success the daemon retries with the credentials attached and the task resumes on its * own — this method does not itself start the transfer. Privileged and Unix-socket-only: a * credential-bearing method must never be reachable from the browser, which is exactly the * boundary event.auth.required's own description draws ('never back through this event, * never into a log') — this is the other half of that promise. Credentials are handed to * the Secret Service, never to SQLite and never logged; save only tells the daemon whether * to persist them there for next time, or use them for this attempt alone. */ "download.provideAuth": { params: DownloadProvideAuthParams; result: DownloadProvideAuthResult }; /** * IDM's 'Refresh Download Address'. Point an existing task at a freshly-issued URL when a * signed link has expired, keeping every byte already on disk. The daemon re-probes and * compares size and validator: if they still match, the transfer resumes from where it * stopped; if they do not, it says so rather than silently restarting. */ "download.refreshUrl": { params: DownloadRefreshUrlParams; result: DownloadRefreshUrlResult }; /** * Drop tasks from the list, optionally deleting the bytes on disk. Privileged: this is the * only method that destroys user data, and the extension is never allowed to reach it. The * daemon deletes the .veloxpart and .veloxpart.meta pair, and the finished file only when * deleteFile is true. */ "download.remove": { params: DownloadRemoveParams; result: DownloadRemoveResult }; /** * Continue paused tasks. Resumption is revalidated with If-Range against the stored ETag * or Last-Modified; a 200 where 206 was expected means the file changed on the server, and * the task moves to failed with a clear error rather than corrupting the part file. */ "download.resume": { params: DownloadResumeParams; result: BulkTaskResult }; /** * Begin or restart the given tasks. A task in 'queued' jumps its queue; a task already * downloading is a no-op reported as changed false. */ "download.start": { params: DownloadStartParams; result: BulkTaskResult }; /** * Change a task's mutable fields. Moving saveDir or filename moves the file on disk in the * same operation, which is what makes dragging a row onto a category work as one RPC. * Privileged: it can name a destination path. */ "download.update": { params: DownloadUpdateParams; result: TaskSummary }; /** * Turn selected crawl results into tasks. This is the only grabber call that creates * downloads, and it names exactly the files the user ticked — a crawl never starts a * download on its own. */ "grabber.harvest": { params: GrabberHarvestParams; result: GrabberHarvestResult }; /** * Start a depth-limited crawl. Nothing is downloaded by this call: it only walks pages and * collects candidate links, which the wizard then shows for selection. Privileged because * an unbounded crawl is a resource commitment the browser must not be able to make on the * user's behalf. */ "grabber.start": { params: GrabberStartParams; result: GrabberStartResult }; /** * Poll one crawl. Also delivered as event.grabber.progress; the poll exists so the wizard * can be reopened on a job it did not start and still catch up. */ "grabber.status": { params: GrabberStatusParams; result: GrabberStatusResult }; /** * Current global speed limit. Privileged: changing or reading the limiter belongs to the * GUI and CLI; the extension shows throughput from event.speed.global instead. */ "limiter.get": { params: LimiterGetParams; result: Limiter }; /** * Set the global token-bucket limit. With applyToRunning true the change re-tunes * transfers already in flight instead of taking effect only on the next task — the Speed * Limiter window's 'apply now' button. */ "limiter.set": { params: Limiter; result: Limiter }; /** * Turn one enumerated variant into a task. The daemon fetches the segments in parallel and * muxes them with ffmpeg; the result is an ordinary task that appears in the list like any * other download. Refused with -32602 when the variant is DRM-protected. */ "media.addVariant": { params: MediaAddVariantParams; result: MediaAddVariantResult }; /** * Parse an HLS or DASH manifest in the daemon and enumerate its renditions. The extension * never parses a manifest — that logic lives in one language, in one place. Variants with * drm true are reported so the UI can grey them out; DRM-protected streams are refused, * not attempted. */ "media.listVariants": { params: MediaListVariantsParams; result: MediaListVariantsResult }; /** * Every queue with its run state and ordering. Not privileged: the extension's 'Add to * Queue' picker needs it. */ "queue.list": { params: QueueListParams; result: QueueListResult }; /** * Rewrite a queue's run order. taskIds must be a permutation of the queue's current * membership; anything else is -32602 rather than a partial reorder, so a stale drag from * an out-of-date view cannot quietly reshuffle the queue. */ "queue.reorder": { params: QueueReorderParams; result: QueueReorderResult }; /** * Start a queue running. The scheduler then admits up to maxConcurrent tasks from it, in * order, and keeps that many running until the queue drains or is stopped. */ "queue.start": { params: QueueStartParams; result: QueueStartResult }; /** * Stop admitting new tasks from a queue. Tasks already running are paused when * pauseRunning is true, and otherwise allowed to finish — the difference between 'stop the * queue' and 'stop everything', which IDM conflates and users trip over. */ "queue.stop": { params: QueueStopParams; result: QueueStopResult }; /** * Create or replace a queue, including its schedule and concurrency cap. Omit queueId to * create. taskIds in the payload is ignored — membership changes through download.update * and queue.reorder so that two clients editing at once cannot silently drop a task. */ "queue.upsert": { params: QueueUpsertParams; result: QueueUpsertResult }; /** * The rules engine's table, in priority order. Privileged: these are the daemon's routing * policy. The extension gets its own narrowed view through capture.getRules instead. */ "rules.list": { params: RulesListParams; result: RulesListResult }; /** * Create, replace, or delete rules in one atomic write. 'upsert' carries the rules to * store and 'remove' the ruleIds to drop; applying both at once means a reprioritisation * never leaves the table in a half-valid state. */ "rules.upsert": { params: RulesUpsertParams; result: RulesUpsertResult }; /** * The schedule for one queue, or every schedule when queueId is null. Backs the Scheduler * window. */ "schedule.get": { params: ScheduleGetParams; result: ScheduleGetResult }; /** * Set or clear a queue's schedule. A null schedule clears it and leaves the queue under * manual control. Times are local wall-clock and are re-evaluated on a DST change rather * than being resolved to absolute instants at set time. */ "schedule.set": { params: ScheduleSetParams; result: ScheduleSetResult }; /** * First call on every connection, on every transport. The daemon compares protocolVersion * majors and refuses a mismatch with -32001 so a stale GUI or extension fails loudly on * connect instead of subtly at the tenth field. On the WebSocket transport a valid token * is required unless the client is about to call session.pair. */ "session.hello": { params: SessionHelloParams; result: SessionHelloResult }; /** * WebSocket transport only. Triggers a GUI or desktop-notification prompt showing a * four-digit code; the user must approve before a token is issued. Failed attempts are * rate-limited to 5/min followed by a 60 s lockout (-32014) so a token cannot be * brute-forced by another local process. The daemon stores only a hash of the token. */ "session.pair": { params: SessionPairParams; result: SessionPairResult }; /** * Choose which notifications this connection receives. Subscribing replaces the previous * selection rather than adding to it, so a client can narrow its firehose without * reconnecting. Nothing is delivered until this is called. */ "session.subscribe": { params: SessionSubscribeParams; result: SessionSubscribeResult }; /** * Read settings. keys null means everything. Privileged: the settings bag names local * filesystem paths and the allowed write roots, which the extension has no business * enumerating — it gets capture.getRules instead. */ "settings.get": { params: SettingsGetParams; result: SettingsGetResult }; /** * Write settings. Only the keys present in values change. Rejected with -32602 if a key is * unknown or a value fails the Settings schema, and with -32011 if a directory key names a * path that cannot be written. Emits event.settings.changed with exactly the keys that * took effect. */ "settings.set": { params: SettingsSetParams; result: SettingsSetResult }; } export type MethodName = keyof MethodMap; export type Params = MethodMap[M]['params']; export type Result = MethodMap[M]['result']; export type Transport = 'uds' | 'ws'; export interface MethodMeta { /** Refused over the WebSocket transport with -32003. */ readonly privileged: boolean; readonly transports: readonly Transport[]; /** How long a client waits before giving up on this call. */ readonly deadlineMs: number; /** Error codes this method is documented to return. */ readonly errors: readonly number[]; } export const METHODS: { readonly [M in MethodName]: MethodMeta } = { "capture.getRules": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 2000, errors: [] }, "capture.offer": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 750, errors: [-32011] }, "category.list": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 2000, errors: [] }, "category.remove": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003, -32602] }, "category.upsert": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003, -32011] }, "download.add": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 5000, errors: [-32011, -32012, -32013] }, "download.addBatch": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 30000, errors: [-32011, -32012] }, "download.cancel": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 5000, errors: [-32010] }, "download.get": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 5000, errors: [-32010] }, "download.list": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 5000, errors: [] }, "download.pause": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 5000, errors: [-32010] }, "download.probe": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 30000, errors: [-32013] }, "download.provideAuth": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003, -32010] }, "download.refreshUrl": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 30000, errors: [-32010, -32013] }, "download.remove": { privileged: true, transports: ['uds'], deadlineMs: 10000, errors: [-32003, -32010] }, "download.resume": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 5000, errors: [-32010] }, "download.start": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 5000, errors: [-32010] }, "download.update": { privileged: true, transports: ['uds'], deadlineMs: 30000, errors: [-32003, -32010, -32011] }, "grabber.harvest": { privileged: true, transports: ['uds'], deadlineMs: 30000, errors: [-32003, -32011] }, "grabber.start": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003] }, "grabber.status": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003, -32602] }, "limiter.get": { privileged: true, transports: ['uds'], deadlineMs: 2000, errors: [-32003] }, "limiter.set": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003, -32602] }, "media.addVariant": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 30000, errors: [-32011, -32602, -32013] }, "media.listVariants": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 30000, errors: [-32013] }, "queue.list": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 2000, errors: [] }, "queue.reorder": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003, -32602] }, "queue.start": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003] }, "queue.stop": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003] }, "queue.upsert": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003] }, "rules.list": { privileged: true, transports: ['uds'], deadlineMs: 2000, errors: [-32003] }, "rules.upsert": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003] }, "schedule.get": { privileged: true, transports: ['uds'], deadlineMs: 2000, errors: [-32003] }, "schedule.set": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003, -32602] }, "session.hello": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 2000, errors: [-32001, -32002] }, "session.pair": { privileged: false, transports: ['ws'], deadlineMs: 120000, errors: [-32003, -32014] }, "session.subscribe": { privileged: false, transports: ['uds', 'ws'], deadlineMs: 2000, errors: [] }, "settings.get": { privileged: true, transports: ['uds'], deadlineMs: 2000, errors: [-32003] }, "settings.set": { privileged: true, transports: ['uds'], deadlineMs: 5000, errors: [-32003, -32602, -32011] }, } as const; export const METHOD_NAMES = Object.keys(METHODS) as MethodName[]; export function isMethodName(v: unknown): v is MethodName { return typeof v === 'string' && Object.prototype.hasOwnProperty.call(METHODS, v); } /** Methods this transport may call. The extension checks before sending so a * privileged call fails in one place rather than as a puzzling -32003. */ export function isAllowedOn(method: MethodName, transport: Transport): boolean { return (METHODS[method].transports as readonly string[]).includes(transport); } /** * The typed client surface. Every transport implements this; the generated * signature is what stops a caller passing download.add's params to download.get. */ export interface VeloxClient { call(method: M, params: Params): Promise>; }