//#region src/types/deck.d.ts
type DeckStats = {
  deck_id: number;
  learn_count: number;
  name: string;
  new_count: number;
  review_count: number;
  total_in_deck: number;
};
type DeckConfig = {
  autoplay: boolean;
  dyn: 1 | false;
  id: number;
  lapse: {
    delays: number[];
    leechAction: number;
    leechFails: number;
    minInt: number;
    mult: number;
  };
  maxTaken: number;
  mod: number;
  name: string;
  new: {
    bury: boolean;
    delays: number[];
    initialFactor: number;
    ints: number[];
    order: number;
    perDay: number;
    separate: boolean;
  };
  replayq: boolean;
  rev: {
    bury: boolean;
    ease4: number;
    fuzz: number;
    ivlFct: number;
    maxIvl: number;
    minSpace: number;
    perDay: number;
  };
  timer: number;
  usn: number;
};
type DeckRequests = Request<'changeDeck', 6, {
  cards: number[];
  deck: string;
}> | Request<'cloneDeckConfigId', 6, {
  cloneFrom: number;
  name: string;
}, false | number> | Request<'createDeck', 6, {
  deck: string;
}, number> | Request<'deckNames', 6, never, string[]> | Request<'deckNamesAndIds', 6, never, Record<string, number>> | Request<'deleteDecks', 6, {
  cardsToo: true;
  decks: string[];
}> | Request<'getDeckConfig', 6, {
  deck: string;
}, DeckConfig> | Request<'getDecks', 6, Record<'cards', number[]>, Record<string, number[]>> | Request<'getDeckStats', 6, {
  decks: string[];
}, Record<string, DeckStats>> | Request<'removeDeckConfigId', 6, {
  configId: number;
}, boolean> | Request<'saveDeckConfig', 6, {
  config: DeckConfig;
}, boolean> | Request<'setDeckConfigId', 6, {
  configId: number;
  decks: string[];
}, boolean>;
//#endregion
//#region src/types/note.d.ts
type NoteModel = 'Basic' | 'Basic (and reversed card)' | 'Basic (type in the answer)' | 'Cloze' | (string & {});
type NoteMedia = {
  data?: string;
  fields?: string[];
  filename: string;
  path?: string;
  skipHash?: string;
  url?: string;
};
type Note = {
  audio?: NoteMedia[];
  deckName: string;
  fields: Record<string, string>;
  modelName: NoteModel;
  picture?: NoteMedia[];
  tags?: string[];
  video?: NoteMedia[];
};
type NoteWithCreationOptions = Note & {
  options?: {
    allowDuplicate?: boolean;
    duplicateScope?: 'deck' | (string & {});
    duplicateScopeOptions?: {
      checkAllModels?: boolean;
      checkChildren?: boolean;
      deckName?: null | string;
    };
  };
};
type NoteRequests = Request<'addNote', 6, {
  note: NoteWithCreationOptions;
}, null | number> | Request<'addNotes', 6, {
  notes: NoteWithCreationOptions[];
}, Array<null | string> | null> | Request<'addTags', 6, {
  notes: number[];
  tags: string;
}> | Request<'canAddNotes', 6, {
  notes: NoteWithCreationOptions[];
}, boolean[]> | Request<'canAddNotesWithErrorDetail', 6, {
  notes: NoteWithCreationOptions[];
}, Array<{
  canAdd: false;
  error: string;
} | {
  canAdd: true;
}>> | Request<'clearUnusedTags', 6, never, string[]> | Request<'deleteNotes', 6, {
  notes: number[];
}> | Request<'findNotes', 6, {
  query: string;
}, number[]> | Request<'getNoteTags', 6, {
  note: number;
}, string[]> | Request<'getTags', 6, never, string[]> | Request<'notesInfo', 6, {
  notes: number[];
}, Array<{
  cards: number[];
  fields: Record<string, {
    order: number;
    value: string;
  }>;
  mod: number;
  modelName: string;
  noteId: number;
  profile: string;
  tags: string[];
}>> | Request<'notesModTime', 6, {
  notes: number[];
}, Array<{
  mod: number;
  noteId: number;
}>> | Request<'removeEmptyNotes', 6> | Request<'removeTags', 6, {
  notes: number[];
  tags: string;
}> | Request<'replaceTags', 6, {
  notes: number[];
  replace_with_tag: string;
  tag_to_replace: string;
}> | Request<'replaceTagsInAllNotes', 6, {
  replace_with_tag: string;
  tag_to_replace: string;
}> | Request<'updateNote', 6, {
  note: {
    audio?: NoteMedia[];
    fields: Record<string, string>;
    id: number;
    picture?: NoteMedia[];
    tags?: string[];
    video?: NoteMedia[];
  } | {
    fields?: Record<string, string>;
    id: number;
    tags: string[];
  };
}> | Request<'updateNoteFields', 6, {
  note: {
    audio?: NoteMedia[];
    fields: Record<string, string>;
    id: number;
    picture?: NoteMedia[];
    video?: NoteMedia[];
  };
}> | Request<'updateNoteModel', 6, {
  note: {
    fields: Record<string, string>;
    id: number;
    modelName: string;
    tags: string[];
  };
}> | Request<'updateNoteTags', 6, {
  note: number;
  tags: string[];
}>;
//#endregion
//#region src/types/graphical.d.ts
type GraphicalRequests = Request<'guiAddCards', 6, {
  note: Note;
}, number> | Request<'guiAnswerCard', 6, {
  ease: number;
}, boolean> | Request<'guiBrowse', 6, {
  query: string;
  reorderCards?: {
    columnId: CardBrowserColumns;
    order: 'ascending' | 'descending';
  };
}, number[]> | Request<'guiCheckDatabase', 6, never, true> | Request<'guiCurrentCard', 6, never, CardInfo | null> | Request<'guiDeckBrowser', 6> | Request<'guiDeckOverview', 6, {
  name: string;
}, boolean> | Request<'guiDeckReview', 6, {
  name: string;
}, boolean> | Request<'guiEditNote', 6, {
  note: number;
}> | Request<'guiExitAnki', 6> | Request<'guiImportFile', 6, {
  path: string;
}> | Request<'guiPlayAudio', 6, never, true> | Request<'guiSelectCard', 6, {
  card: number;
}, boolean> | Request<'guiSelectedNotes', 6, never, number[]> | Request<'guiSelectNote', 6, {
  note: number;
}, boolean> | Request<'guiShowAnswer', 6, never, boolean> | Request<'guiShowQuestion', 6, never, boolean> | Request<'guiStartCardTimer', 6, never, true> | Request<'guiUndo', 6, never, boolean>;
//#endregion
//#region src/types/media.d.ts
type MediaRequests = Request<'deleteMediaFile', 6, {
  filename: string;
}> | Request<'getMediaDirPath', 6, never, string> | Request<'getMediaFilesNames', 6, {
  pattern: string;
}, string[]> | Request<'retrieveMediaFile', 6, {
  filename: string;
}, false | string> | Request<'storeMediaFile', 6, {
  data?: string;
  deleteExisting?: boolean;
  filename: string;
  path?: string;
  url?: string;
}, string>;
//#endregion
//#region src/types/miscellaneous.d.ts
type MiscellaneousRequests = Request<'apiReflect', 6, {
  actions: null | string[];
  scopes: Array<'actions'>;
}, {
  actions: string[];
  scopes: string[];
}> | Request<'exportPackage', 6, {
  deck: string;
  includeSched?: boolean;
  path: string;
}, boolean> | Request<'getActiveProfile', 6, never, string> | Request<'getProfiles', 6, never, string[]> | Request<'importPackage', 6, {
  path: string;
}, boolean> | Request<'loadProfile', 6, {
  name: string;
}, true> | Request<'multi', 6, // Crazy, have to call this experimental
{
  actions: Array<{
    action: Requests['action'];
    params?: Requests['params'];
    version?: number;
  }>;
}, Array<Requests['response'] | {
  error: null | string;
  result: Requests['response'];
}>> | Request<'reloadCollection', 6> | Request<'requestPermission', 6, never, {
  permission: 'denied';
} | {
  permission: 'granted';
  requireApiKey: boolean;
  version: boolean;
}> | Request<'sync', 6> | Request<'version', 6, never, number>;
//#endregion
//#region src/types/model.d.ts
type ModelField = {
  collapsed: boolean;
  description: string;
  excludeFromSearch: boolean;
  font: string;
  id: number;
  name: string;
  ord: number;
  plainText: boolean;
  preventDeletion: boolean;
  rtl: boolean;
  size: number;
  sticky: boolean;
  tag: null;
};
type ModelTemplate = {
  afmt: string;
  bafmt: string;
  bfont: string;
  bqfmt: string;
  bsize: number;
  did: null;
  id: number;
  name: string;
  ord: number;
  qfmt: string;
};
type Model = {
  css: string;
  did: null;
  flds: ModelField[];
  id: number;
  latexPost: string;
  latexPre: string;
  latexsvg: boolean;
  mod: number;
  name: string;
  originalStockKind: number;
  req: Array<[number, string, number[]]>;
  sortf: number;
  tmpls: ModelTemplate[];
  type: number;
  usn: number;
};
type ModelToCreate = {
  cardTemplates: Array<{
    [key: string]: string;
    Back: string;
    Front: string;
  }>;
  css?: string;
  inOrderFields: string[];
  isCloze?: boolean;
  modelName: string;
};
type ModelRequests = Request<'createModel', 6, ModelToCreate, Model> | Request<'findAndReplaceInModels', 6, {
  model: {
    back: boolean;
    css: boolean;
    fieldText: string;
    front: boolean;
    modelName: string;
    replaceText: string;
  };
}, number> | Request<'findModelsById', 6, {
  modelIds: number[];
}, Model[]> | Request<'findModelsByName', 6, {
  modelNames: string[];
}, Model[]> | Request<'modelFieldAdd', 6, {
  fieldName: string;
  index: number;
  modelName: string;
}> | Request<'modelFieldDescriptions', 6, {
  description: string;
  fieldName: string;
  modelName: string;
}, boolean> | Request<'modelFieldFonts', 6, {
  modelName: string;
}, Record<string, {
  font: string;
  size: number;
}>> | Request<'modelFieldNames', 6, {
  modelName: string;
}, string[]> | Request<'modelFieldRemove', 6, {
  fieldName: string;
  modelName: string;
}> | Request<'modelFieldRename', 6, {
  modelName: string;
  newFieldName: string;
  oldFieldName: string;
}> | Request<'modelFieldReposition', 6, {
  fieldName: string;
  index: number;
  modelName: string;
}> | Request<'modelFieldSetDescription', 6, {
  fieldName: string;
  index: number;
  modelName: string;
}> | Request<'modelFieldSetFont', 6, {
  fieldName: string;
  font: string;
  modelName: string;
}> | Request<'modelFieldSetFontSize', 6, {
  fieldName: string;
  fontSize: number;
  modelName: string;
}> | Request<'modelFieldsOnTemplates', 6, {
  modelName: string;
}, Record<string, [string[], string[]]>> | Request<'modelNames', 6, never, string[]> | Request<'modelNamesAndIds', 6, never, Record<string, number>> | Request<'modelStyling', 6, {
  modelName: string;
}, {
  css: string;
}> | Request<'modelTemplateAdd', 6, {
  modelName: string;
  template: {
    [key: string]: string;
    Back: string;
    Front: string;
  };
}> | Request<'modelTemplateRemove', 6, {
  modelName: string;
  templateName: string;
}> | Request<'modelTemplateRename', 6, {
  modelName: string;
  newTemplateName: string;
  oldTemplateName: string;
}> | Request<'modelTemplateReposition', 6, {
  index: number;
  modelName: string;
  templateName: string;
}> | Request<'modelTemplates', 6, {
  modelName: string;
}, Record<string, {
  [key: string]: string;
  Back: string;
  Front: string;
}>> | Request<'updateModelStyling', 6, {
  model: {
    css: string;
    name: string;
  };
}> | Request<'updateModelTemplates', 6, {
  model: {
    name: string;
    templates: Record<string, {
      Back?: string;
      Front?: string;
    }>;
  };
}>;
//#endregion
//#region src/types/statistic.d.ts
type ReviewStatisticTuple = [reviewTime: number, cardID: number, usn: number, buttonPressed: number, newInterval: number, previousInterval: number, newFactor: number, reviewDuration: number, reviewType: number];
type StatisticRequests = Request<'cardReviews', 6, {
  deck: string;
  startID: number;
}, ReviewStatisticTuple[]> | Request<'getCollectionStatsHTML', 6, {
  wholeCollection: boolean;
}, string> | Request<'getLatestReviewID', 6, {
  deck: string;
}, number> | Request<'getNumCardsReviewedByDay', 6, never, Array<[string, number]>> | Request<'getNumCardsReviewedToday', 6, never, number> | Request<'getReviewsOfCards', 6, {
  cards: string[];
}, Record<string, Array<{
  /** ButtonPressed */ease: number; /** NewFactor */
  factor: number; /** ReviewTime */
  id: number; /** NewInterval */
  ivl: number; /** PreviousInterval */
  lastIvl: number; /** ReviewDuration */
  time: number; /** ReviewType */
  type: number; /** Usn */
  usn: number;
}>>> | Request<'insertReviews', 6, {
  reviews: ReviewStatisticTuple[];
}>;
//#endregion
//#region src/types/shared.d.ts
/**
 * Abstract wrapper over an Anki Connect action / response
 */
type Request<Action extends string, Version extends AnkiConnectVersion, Params = never, Result = null> = {
  action: Action;
  params: Params;
  response: {
    error: null | string;
    result: Result;
  };
  version: Version;
};
/**
 * Requests
 */
type Requests = CardRequests | DeckRequests | GraphicalRequests | MediaRequests | MiscellaneousRequests | ModelRequests | NoteRequests | StatisticRequests;
type AnkiConnectVersion = 6;
type Actions = Requests['action'];
type ActionsWithParams = { [K in Actions]: ParamsForAction<K> extends never ? never : K }[Actions];
type ActionsWithoutParams = { [K in Actions]: ParamsForAction<K> extends never ? K : never }[Actions];
type ParamsForAction<T extends Requests['action']> = Extract<Requests, {
  action: T;
}>['params'];
type ResponseForAction<T extends Requests['action']> = Extract<Requests, {
  action: T;
}>['response'];
//#endregion
//#region src/types/card.d.ts
type CardBrowserColumns = 'answer' | 'cardDue' | 'cardEase' | 'cardIvl' | 'cardLapses' | 'cardMod' | 'cardReps' | 'deck' | 'note' | 'noteCrt' | 'noteFld' | 'noteMod' | 'noteTags' | 'question' | 'template' | (string & {});
type CardValueKeys = 'data' | 'did' | 'due' | 'factor' | 'flags' | 'id' | 'ivl' | 'lapses' | 'left' | 'mod' | 'odid' | 'odue' | 'ord' | 'queue' | 'reps' | 'type' | 'usn';
type CardInfo = {
  answer: string;
  buttons?: number[];
  cardId: number;
  css: string;
  deckName: string;
  due: number;
  fieldOrder: number;
  fields: Record<string, {
    order: number;
    value: string;
  }>;
  interval: number;
  lapses: number;
  left: number;
  mod: number;
  modelName: string;
  nextReviews: string[];
  note: number;
  ord: number;
  question: string;
  queue: number;
  reps: number;
  template: string;
  type: number;
};
type CardRequests = Request<'answerCards', 6, {
  answers: Array<{
    cardId: number;
    ease: number;
  }>;
}, boolean[]> | Request<'areDue', 6, {
  cards: number[];
}, boolean[]> | Request<'areSuspended', 6, {
  cards: number[];
}, Array<boolean | null>> | Request<'cardsInfo', 6, {
  cards: number[];
}, CardInfo[]> | Request<'cardsModTime', 6, {
  cards: number[];
}, {
  cardId: number;
  mod: number;
}> | Request<'cardsToNotes', 6, {
  cards: number[];
}, number[]> | Request<'findCards', 6, {
  query: string;
}, number[]> | Request<'forgetCards', 6, {
  cards: number[];
}> | Request<'getEaseFactors', 6, {
  cards: number[];
}, number[]> | Request<'getIntervals', 6, {
  cards: number[];
  complete?: boolean;
}, number[] | number[][]> | Request<'relearnCards', 6, {
  cards: number[];
}> | Request<'setDueDate', 6, {
  cards: number[];
  days: string;
}, boolean> | Request<'setEaseFactors', 6, {
  cards: number[];
  easeFactors: number[];
}, boolean[]> | Request<'setSpecificValueOfCard', 6, {
  card: number;
  keys: CardValueKeys[];
  newValues: string[];
}, boolean[]> | Request<'suspend', 6, {
  cards: number[];
}, boolean> | Request<'suspended', 6, {
  card: number;
}, boolean> | Request<'unsuspend', 6, {
  cards: number[];
}, boolean>;
//#endregion
//#region src/client.d.ts
/**
 * Subset of built-in Fetch interface that's actually used by Anki, for ease of
 * external re-implementation when passing a custom fetch function to
 * YankiClient.
 */
type YankiFetchAdapter = (input: string, init?: {
  body?: string;
  headers?: Record<string, string>;
  method?: string;
  mode?: RequestMode;
}) => Promise<undefined | {
  headers: Headers | Record<string, string>;
  json(): Promise<any>;
  status: number;
}>;
/** Optional options to pass when instantiating a new YankiConnect instance. */
type YankiConnectOptions = {
  /**
   * Attempt to open the desktop Anki.app if it's not already running.
   *
   * - `true` will always attempt to open Anki _when a request is made_. This
   *   might introduce significant latency on the first launch.
   * - `false` will never attempt to open Anki. Requests will fail until something
   *   or someone else opens the Anki app.
   * - `immediately` is a special option that will open Anki when the client is
   *   instantiated.
   *
   * The Anki desktop app must be running for the client and the underlying
   * AnkiConnect service to work.
   *
   * Currently supported on macOS only.
   *
   * The client does not attempt to close the app.
   *
   * @default false
   */
  autoLaunch: 'immediately' | boolean;
  /**
   * Advanced option to customize the resource fetch implementation used to make
   * requests to AnkiConnect.
   *
   * Note that the signature reflects the subset of the built-in Fetch interface
   * that's actually used by yanki-connect.
   *
   * The exact signature of this option is subject to change in the future.
   *
   * @default fetch
   */
  fetchAdapter: undefined | YankiFetchAdapter;
  /**
   * Host where the AnkiConnect service is running.
   *
   * @default 'http://127.0.0.1'
   */
  host: string;
  /**
   * AnkiConnect security key (optional)
   *
   * @default undefined
   */
  key: string | undefined;
  /**
   * Port where the AnkiConnect service is running.
   *
   * @default 8765
   */
  port: number;
  /**
   * AnkiConnect API version.
   *
   * Only API version 6 is supported for now.
   *
   * @default 6
   */
  version: AnkiConnectVersion;
};
declare const defaultYankiConnectOptions: YankiConnectOptions;
/**
 * **YankiConnect is a client for the [AnkiConnect
 * API](https://git.sr.ht/~foosoft/anki-connect/tree/25.11.9.0/item/README.md)**.
 *
 * It implements every endpoint from AnkiConnect version 25.11.9.0, released
 * 2025-11-09.
 *
 * Inline documentation is by the AnkiConnect authors, generated from [the
 * readme.md](https://git.sr.ht/~foosoft/anki-connect/tree/25.11.9.0/item/README.md)
 */
declare class YankiConnect {
  /**
   * **Card Actions**
   *
   * [Documentation](https://git.sr.ht/~foosoft/anki-connect/tree/25.11.9.0/item/README.md#card-actions)
   */
  readonly card: {
    /**
     * Answer cards. Ease is between 1 (Again) and 4 (Easy). Will start the
     * timer immediately before answering. Returns true if card exists, `false`
     * otherwise.
     */
    answerCards: (params: {
      answers: Array<{
        cardId: number;
        ease: number;
      }>;
    }) => Promise<boolean[]>;
    /**
     * Returns an array indicating whether each of the given cards is due (in
     * the same order). Note: cards in the learning queue with a large interval
     * (over 20 minutes) are treated as not due until the time of their interval
     * has passed, to match the way Anki treats them when reviewing.
     */
    areDue: (params: {
      cards: number[];
    }) => Promise<boolean[]>;
    /**
     * Returns an array indicating whether each of the given cards is suspended
     * (in the same order). If card doesn’t exist returns `null`.
     */
    areSuspended: (params: {
      cards: number[];
    }) => Promise<(boolean | null)[]>;
    /**
     * Returns a list of objects containing for each card ID the card fields,
     * front and back sides including CSS, note type, the note that the card
     * belongs to, and deck name, last modification timestamp as well as ease
     * and interval.
     */
    cardsInfo: (params: {
      cards: number[];
    }) => Promise<CardInfo[]>;
    /**
     * Returns a list of objects containing for each card ID the modification
     * time. This function is about 15 times faster than executing `cardsInfo`.
     */
    cardsModTime: (params: {
      cards: number[];
    }) => Promise<{
      cardId: number;
      mod: number;
    }>;
    /**
     * Returns an unordered array of note IDs for the given card IDs. For cards
     * with the same note, the ID is only given once in the array.
     */
    cardsToNotes: (params: {
      cards: number[];
    }) => Promise<number[]>;
    /**
     * Returns an array of card IDs for a given query. Functionally identical to
     * `guiBrowse` but doesn’t use the GUI for better performance.
     */
    findCards: (params: {
      query: string;
    }) => Promise<number[]>;
    /**
     * Forget cards, making the cards new again.
     */
    forgetCards: (params: {
      cards: number[];
    }) => Promise<null>;
    /**
     * Returns an array with the ease factor for each of the given cards (in the
     * same order).
     */
    getEaseFactors: (params: {
      cards: number[];
    }) => Promise<number[]>;
    /**
     * Returns an array of the most recent intervals for each given card ID, or
     * a 2-dimensional array of all the intervals for each given card ID when
     * complete is `true`. Negative intervals are in seconds and positive
     * intervals in days.
     */
    getIntervals: (params: {
      cards: number[];
      complete?: boolean;
    }) => Promise<number[] | number[][]>;
    /**
     * Make cards be “relearning”.
     */
    relearnCards: (params: {
      cards: number[];
    }) => Promise<null>;
    /**
     * Set Due Date. Turns cards into review cards if they are new, and makes
     * them due on a certain date.
     *
     * - 0 = today
     * - 1! = tomorrow + change interval to 1
     * - 3-7 = random choice of 3-7 days
     */
    setDueDate: (params: {
      cards: number[];
      days: string;
    }) => Promise<boolean>;
    /**
     * Sets ease factor of cards by card ID; returns `true` if successful (all
     * cards existed) or `false` otherwise.
     */
    setEaseFactors: (params: {
      cards: number[];
      easeFactors: number[];
    }) => Promise<boolean[]>;
    /**
     * Sets specific value of a single card. Given the risk of wreaking havoc in
     * the database when changing some of the values of a card, some of the keys
     * require the argument “warning_check” set to True. This can be used to set
     * a card’s flag, change it’s ease factor, change the review order in a
     * filtered deck and change the column “data” (not currently used by anki
     * apparently), and many other values. A list of values and explanation of
     * their respective utility can be found at [AnkiDroid’s
     * wiki](https://github.com/ankidroid/Anki-Android/wiki/Database-Structure).
     */
    setSpecificValueOfCard: (params: {
      card: number;
      keys: ("data" | "did" | "due" | "factor" | "flags" | "id" | "ivl" | "lapses" | "left" | "mod" | "odid" | "odue" | "ord" | "queue" | "reps" | "type" | "usn")[];
      newValues: string[];
    }) => Promise<boolean[]>;
    /**
     * Suspend cards by card ID; returns `true` if successful (at least one card
     * wasn’t already suspended) or `false` otherwise.
     */
    suspend: (params: {
      cards: number[];
    }) => Promise<boolean>;
    /**
     * Check if card is suspended by its ID. Returns `true` if suspended,
     * `false` otherwise.
     */
    suspended: (params: {
      card: number;
    }) => Promise<boolean>;
    /**
     * Unsuspend cards by card ID; returns `true` if successful (at least one
     * card was previously suspended) or `false` otherwise.
     */
    unsuspend: (params: {
      cards: number[];
    }) => Promise<boolean>;
  };
  /**
   * **Deck Actions**
   *
   * [Documentation](https://git.sr.ht/~foosoft/anki-connect/tree/25.11.9.0/item/README.md#deck-actions)
   */
  readonly deck: {
    /**
     * Moves cards with the given IDs to a different deck, creating the deck if
     * it doesn’t exist yet.
     */
    changeDeck: (params: {
      cards: number[];
      deck: string;
    }) => Promise<null>;
    /**
     * Creates a new configuration group with the given name, cloning from the
     * group with the given ID, or from the default group if this is
     * unspecified. Returns the ID of the new configuration group, or `false` if
     * the specified group to clone from does not exist.
     */
    cloneDeckConfigId: (params: {
      cloneFrom: number;
      name: string;
    }) => Promise<number | false>;
    /**
     * Create a new empty deck. Will not overwrite a deck that exists with the
     * same name.
     */
    createDeck: (params: {
      deck: string;
    }) => Promise<number>;
    /**
     * Gets the complete list of deck names for the current user.
     */
    deckNames: () => Promise<string[]>;
    /**
     * Gets the complete list of deck names and their respective IDs for the
     * current user.
     */
    deckNamesAndIds: () => Promise<Record<string, number>>;
    /**
     * Deletes decks with the given names. The argument `cardsToo` must be
     * specified and set to `true`.
     */
    deleteDecks: (params: {
      cardsToo: true;
      decks: string[];
    }) => Promise<null>;
    /**
     * Gets the configuration group object for the given deck.
     */
    getDeckConfig: (params: {
      deck: string;
    }) => Promise<{
      autoplay: boolean;
      dyn: 1 | false;
      id: number;
      lapse: {
        delays: number[];
        leechAction: number;
        leechFails: number;
        minInt: number;
        mult: number;
      };
      maxTaken: number;
      mod: number;
      name: string;
      new: {
        bury: boolean;
        delays: number[];
        initialFactor: number;
        ints: number[];
        order: number;
        perDay: number;
        separate: boolean;
      };
      replayq: boolean;
      rev: {
        bury: boolean;
        ease4: number;
        fuzz: number;
        ivlFct: number;
        maxIvl: number;
        minSpace: number;
        perDay: number;
      };
      timer: number;
      usn: number;
    }>;
    /**
     * Accepts an array of card IDs and returns an object with each deck name as
     * a key, and its value an array of the given cards which belong to it.
     */
    getDecks: (params: Record<"cards", number[]>) => Promise<Record<string, number[]>>;
    /**
     * ```
     * 	  Gets statistics such as total cards and cards due for the given decks.
     * ```
     */
    getDeckStats: (params: {
      decks: string[];
    }) => Promise<Record<string, {
      deck_id: number;
      learn_count: number;
      name: string;
      new_count: number;
      review_count: number;
      total_in_deck: number;
    }>>;
    /**
     * Removes the configuration group with the given ID, returning `true` if
     * successful, or `false` if attempting to remove either the default
     * configuration group (ID = 1) or a configuration group that does not
     * exist.
     */
    removeDeckConfigId: (params: {
      configId: number;
    }) => Promise<boolean>;
    /**
     * Saves the given configuration group, returning `true` on success or
     * `false` if the ID of the configuration group is invalid (such as when it
     * does not exist).
     */
    saveDeckConfig: (params: {
      config: {
        autoplay: boolean;
        dyn: 1 | false;
        id: number;
        lapse: {
          delays: number[];
          leechAction: number;
          leechFails: number;
          minInt: number;
          mult: number;
        };
        maxTaken: number;
        mod: number;
        name: string;
        new: {
          bury: boolean;
          delays: number[];
          initialFactor: number;
          ints: number[];
          order: number;
          perDay: number;
          separate: boolean;
        };
        replayq: boolean;
        rev: {
          bury: boolean;
          ease4: number;
          fuzz: number;
          ivlFct: number;
          maxIvl: number;
          minSpace: number;
          perDay: number;
        };
        timer: number;
        usn: number;
      };
    }) => Promise<boolean>;
    /**
     * Changes the configuration group for the given decks to the one with the
     * given ID. Returns `true` on success or `false` if the given configuration
     * group or any of the given decks do not exist.
     */
    setDeckConfigId: (params: {
      configId: number;
      decks: string[];
    }) => Promise<boolean>;
  };
  /**
   * **Graphical Actions**
   *
   * [Documentation](https://git.sr.ht/~foosoft/anki-connect/tree/25.11.9.0/item/README.md#graphical-actions)
   */
  readonly graphical: {
    /**
     * Invokes the _Add Cards_ dialog, presets the note using the given deck and
     * model, with the provided field values and tags. Invoking it multiple
     * times closes the old window and _reopen the window_ with the new provided
     * values.
     *
     * Audio, video, and picture files can be embedded into the fields via the
     * `audio`, `video`, and `picture` keys, respectively. Refer to the
     * documentation of `addNote` and `storeMediaFile` for an explanation of
     * these fields.
     *
     * The result is the ID of the note which would be added, if the user chose
     * to confirm the _Add Cards_ dialogue.
     */
    guiAddCards: (params: {
      note: Note;
    }) => Promise<number>;
    /**
     * Answers the current card; returns `true` if succeeded or `false`
     * otherwise. Note that the answer for the current card must be displayed
     * before before any answer can be accepted by Anki.
     */
    guiAnswerCard: (params: {
      ease: number;
    }) => Promise<boolean>;
    /**
     * Invokes the _Card Browser_ dialog and searches for a given query. Returns
     * an array of identifiers of the cards that were found. Query syntax is
     * [documented here](https://docs.ankiweb.net/searching.html).
     *
     * Optionally, the `reorderCards` property can be provided to reorder the
     * cards shown in the _Card Browser_. This is an array including the `order`
     * and `columnId` objects. `order` can be either `ascending` or `descending`
     * while `columnId` can be one of several column identifiers (as documented
     * in the [Anki source
     * code](https://github.com/ankitects/anki/blob/main/rslib/src/browser_table.rs)).
     * The specified column needs to be visible in the _Card Browser_.
     */
    guiBrowse: (params: {
      query: string;
      reorderCards?: {
        columnId: CardBrowserColumns;
        order: "ascending" | "descending";
      };
    }) => Promise<number[]>;
    /**
     * Requests a database check, but returns immediately without waiting for
     * the check to complete. Therefore, the action will always return `true`
     * even if errors are detected during the database check.
     */
    guiCheckDatabase: () => Promise<true>;
    /**
     * Returns information about the current card or `null` if not in review
     * mode.
     */
    guiCurrentCard: () => Promise<CardInfo | null>;
    /**
     * Opens the _Deck Browser_ dialog.
     */
    guiDeckBrowser: () => Promise<null>;
    /**
     * Opens the _Deck Overview_ dialog for the deck with the given name;
     * returns `true` if succeeded or `false` otherwise.
     */
    guiDeckOverview: (params: {
      name: string;
    }) => Promise<boolean>;
    /**
     * Starts review for the deck with the given name; returns `true` if
     * succeeded or `false` otherwise.
     */
    guiDeckReview: (params: {
      name: string;
    }) => Promise<boolean>;
    /**
     * Opens the _Edit_ dialog with a note corresponding to given note ID. The
     * dialog is similar to the _Edit Current_ dialog, but:
     *
     * - Has a Preview button to preview the cards for the note
     * - Has a Browse button to open the browser with these cards
     * - Has Previous/Back buttons to navigate the history of the dialog
     * - Has no bar with the Close button
     */
    guiEditNote: (params: {
      note: number;
    }) => Promise<null>;
    /**
     * Schedules a request to gracefully close Anki. This operation is
     * asynchronous, so it will return immediately and won’t wait until the Anki
     * process actually terminates.
     */
    guiExitAnki: () => Promise<null>;
    /**
     * Invokes the _Import… (Ctrl+Shift+I)_ dialog with an optional file path.
     * Brings up the dialog for user to review the import. Supports all file
     * types that Anki supports. Brings open file dialog if no path is provided.
     * Forward slashes must be used in the path on Windows. Only supported for
     * Anki 2.1.52+.
     */
    guiImportFile: (params: {
      path: string;
    }) => Promise<null>;
    /**
     * Plays any Audio for the current side of the current card; returns true if
     * succeeded or false otherwise.
     */
    guiPlayAudio: () => Promise<true>;
    /**
     * Finds the open instance of the Card Browser dialog and selects a card
     * given a card identifier. Returns true if the Card Browser is open, false
     * otherwise.
     */
    guiSelectCard: (params: {
      card: number;
    }) => Promise<boolean>;
    /**
     * Finds the open instance of the _Card Browser_ dialog and returns an array
     * of identifiers of the notes that are selected. Returns an empty list if
     * the browser is not open.
     */
    guiSelectedNotes: () => Promise<number[]>;
    /**
     * @deprecated Actually selects card IDs. Use `guiSelectCard` instead.'
     */
    guiSelectNote: (params: {
      note: number;
    }) => Promise<boolean>;
    /**
     * Shows answer text for the current card; returns `true` if in review mode
     * or `false` otherwise.
     */
    guiShowAnswer: () => Promise<boolean>;
    /**
     * Shows question text for the current card; returns `true` if in review
     * mode or `false` otherwise.
     */
    guiShowQuestion: () => Promise<boolean>;
    /**
     * Starts or resets the `timerStarted` value for the current card. This is
     * useful for deferring the start time to when it is displayed via the API,
     * allowing the recorded time taken to answer the card to be more accurate
     * when calling `guiAnswerCard`.
     */
    guiStartCardTimer: () => Promise<true>;
    /**
     * Undo the last action / card; returns `true` if succeeded or `false`
     * otherwise.
     */
    guiUndo: () => Promise<boolean>;
  };
  /**
   * **Media Actions**
   *
   * [Documentation](https://git.sr.ht/~foosoft/anki-connect/tree/25.11.9.0/item/README.md#media-actions)
   */
  readonly media: {
    /**
     * Deletes the specified file inside the media folder.
     */
    deleteMediaFile: (params: {
      filename: string;
    }) => Promise<null>;
    /**
     * Gets the full path to the `collection.media` folder of the currently
     * opened profile.
     */
    getMediaDirPath: () => Promise<string>;
    /**
     * Gets the names of media files matched the pattern. Returning all names by
     * default.
     */
    getMediaFilesNames: (params: {
      pattern: string;
    }) => Promise<string[]>;
    /**
     * Retrieves the base64-encoded contents of the specified file, returning
     * `false` if the file does not exist.
     */
    retrieveMediaFile: (params: {
      filename: string;
    }) => Promise<string | false>;
    /**
     * Stores a file with the specified base64-encoded contents inside the media
     * folder. Alternatively you can specify a absolute file path, or a url from
     * where the file shell be downloaded. If more than one of `data`, `path`
     * and `url` are provided, the `data` field will be used first, then `path`,
     * and finally `url`. To prevent Anki from removing files not used by any
     * cards (e.g. for configuration files), prefix the filename with an
     * underscore. These files are still synchronized to AnkiWeb. Any existing
     * file with the same name is deleted by default. Set `deleteExisting` to
     * `false` to prevent that by [letting Anki give the new file a
     * non-conflicting
     * name](https://github.com/ankitects/anki/blob/aeba725d3ea9628c73300648f748140db3fdd5ed/rslib/src/media/files.rs#L194).
     */
    storeMediaFile: (params: {
      data?: string;
      deleteExisting?: boolean;
      filename: string;
      path?: string;
      url?: string;
    }) => Promise<string>;
  };
  /**
   * **Miscellaneous Actions**
   *
   * [Documentation](https://git.sr.ht/~foosoft/anki-connect/tree/25.11.9.0/item/README.md#miscellaneous-actions)
   */
  readonly miscellaneous: {
    /**
     * Gets information about the AnkiConnect APIs available. The request
     * supports the following params:
     *
     * - `scopes` - An array of scopes to get reflection information about. The
     *   only currently supported value is `"actions"`.
     * - `actions` - Either `null` or an array of API method names to check for.
     *   If the value is `null`, the result will list all of the available API
     *   actions. If the value is an array of strings, the result will only
     *   contain actions which were in this array.
     */
    apiReflect: (params: {
      actions: null | string[];
      scopes: Array<"actions">;
    }) => Promise<{
      actions: string[];
      scopes: string[];
    }>;
    /**
     * Exports a given deck in `.apkg` format. Returns `true` if successful or
     * `false` otherwise. The optional property `includeSched` (default is
     * `false`) can be specified to include the cards’ scheduling data.
     */
    exportPackage: (params: {
      deck: string;
      includeSched?: boolean;
      path: string;
    }) => Promise<boolean>;
    /**
     * Retrieve the active profile.
     */
    getActiveProfile: () => Promise<string>;
    /**
     * Retrieve the list of profiles.
     */
    getProfiles: () => Promise<string[]>;
    /**
     * Imports a file in `.apkg` format into the collection. Returns `true` if
     * successful or `false` otherwise. Note that the file path is relative to
     * Anki’s collection.media folder, not to the client.
     */
    importPackage: (params: {
      path: string;
    }) => Promise<boolean>;
    /**
     * Selects the profile specified in request.
     */
    loadProfile: (params: {
      name: string;
    }) => Promise<true>;
    /**
     * Performs multiple actions in one request, returning an array with the
     * response of each action (in the given order).
     */
    multi: (params: {
      actions: Array<{
        action: Requests["action"];
        params?: Requests["params"];
        version?: number;
      }>;
    }) => Promise<({
      error: null | string;
      result: boolean[];
    } | {
      error: null | string;
      result: (boolean | null)[];
    } | {
      error: null | string;
      result: CardInfo[];
    } | {
      error: null | string;
      result: {
        cardId: number;
        mod: number;
      };
    } | {
      error: null | string;
      result: number[];
    } | {
      error: null | string;
      result: null;
    } | {
      error: null | string;
      result: number[] | number[][];
    } | {
      error: null | string;
      result: boolean;
    } | {
      error: null | string;
      result: number | false;
    } | {
      error: null | string;
      result: number;
    } | {
      error: null | string;
      result: string[];
    } | {
      error: null | string;
      result: Record<string, number>;
    } | {
      error: null | string;
      result: {
        autoplay: boolean;
        dyn: 1 | false;
        id: number;
        lapse: {
          delays: number[];
          leechAction: number;
          leechFails: number;
          minInt: number;
          mult: number;
        };
        maxTaken: number;
        mod: number;
        name: string;
        new: {
          bury: boolean;
          delays: number[];
          initialFactor: number;
          ints: number[];
          order: number;
          perDay: number;
          separate: boolean;
        };
        replayq: boolean;
        rev: {
          bury: boolean;
          ease4: number;
          fuzz: number;
          ivlFct: number;
          maxIvl: number;
          minSpace: number;
          perDay: number;
        };
        timer: number;
        usn: number;
      };
    } | {
      error: null | string;
      result: Record<string, number[]>;
    } | {
      error: null | string;
      result: Record<string, {
        deck_id: number;
        learn_count: number;
        name: string;
        new_count: number;
        review_count: number;
        total_in_deck: number;
      }>;
    } | {
      error: null | string;
      result: true;
    } | {
      error: null | string;
      result: CardInfo | null;
    } | {
      error: null | string;
      result: string;
    } | {
      error: null | string;
      result: string | false;
    } | {
      error: null | string;
      result: {
        actions: string[];
        scopes: string[];
      };
    } | {
      error: null | string;
      result: ({
        error: null | string;
        result: boolean[];
      } | {
        error: null | string;
        result: (boolean | null)[];
      } | {
        error: null | string;
        result: CardInfo[];
      } | {
        error: null | string;
        result: {
          cardId: number;
          mod: number;
        };
      } | {
        error: null | string;
        result: number[];
      } | {
        error: null | string;
        result: null;
      } | {
        error: null | string;
        result: number[] | number[][];
      } | {
        error: null | string;
        result: boolean;
      } | {
        error: null | string;
        result: number | false;
      } | {
        error: null | string;
        result: number;
      } | {
        error: null | string;
        result: string[];
      } | {
        error: null | string;
        result: Record<string, number>;
      } | {
        error: null | string;
        result: {
          autoplay: boolean;
          dyn: 1 | false;
          id: number;
          lapse: {
            delays: number[];
            leechAction: number;
            leechFails: number;
            minInt: number;
            mult: number;
          };
          maxTaken: number;
          mod: number;
          name: string;
          new: {
            bury: boolean;
            delays: number[];
            initialFactor: number;
            ints: number[];
            order: number;
            perDay: number;
            separate: boolean;
          };
          replayq: boolean;
          rev: {
            bury: boolean;
            ease4: number;
            fuzz: number;
            ivlFct: number;
            maxIvl: number;
            minSpace: number;
            perDay: number;
          };
          timer: number;
          usn: number;
        };
      } | {
        error: null | string;
        result: Record<string, number[]>;
      } | {
        error: null | string;
        result: Record<string, {
          deck_id: number;
          learn_count: number;
          name: string;
          new_count: number;
          review_count: number;
          total_in_deck: number;
        }>;
      } | {
        error: null | string;
        result: true;
      } | {
        error: null | string;
        result: CardInfo | null;
      } | {
        error: null | string;
        result: string;
      } | {
        error: null | string;
        result: string | false;
      } | {
        error: null | string;
        result: {
          actions: string[];
          scopes: string[];
        };
      } | /*elided*/any | {
        error: null | string;
        result: {
          permission: "denied";
        } | {
          permission: "granted";
          requireApiKey: boolean;
          version: boolean;
        };
      } | {
        error: null | string;
        result: {
          css: string;
          did: null;
          flds: {
            collapsed: boolean;
            description: string;
            excludeFromSearch: boolean;
            font: string;
            id: number;
            name: string;
            ord: number;
            plainText: boolean;
            preventDeletion: boolean;
            rtl: boolean;
            size: number;
            sticky: boolean;
            tag: null;
          }[];
          id: number;
          latexPost: string;
          latexPre: string;
          latexsvg: boolean;
          mod: number;
          name: string;
          originalStockKind: number;
          req: Array<[number, string, number[]]>;
          sortf: number;
          tmpls: {
            afmt: string;
            bafmt: string;
            bfont: string;
            bqfmt: string;
            bsize: number;
            did: null;
            id: number;
            name: string;
            ord: number;
            qfmt: string;
          }[];
          type: number;
          usn: number;
        };
      } | {
        error: null | string;
        result: {
          css: string;
          did: null;
          flds: {
            collapsed: boolean;
            description: string;
            excludeFromSearch: boolean;
            font: string;
            id: number;
            name: string;
            ord: number;
            plainText: boolean;
            preventDeletion: boolean;
            rtl: boolean;
            size: number;
            sticky: boolean;
            tag: null;
          }[];
          id: number;
          latexPost: string;
          latexPre: string;
          latexsvg: boolean;
          mod: number;
          name: string;
          originalStockKind: number;
          req: Array<[number, string, number[]]>;
          sortf: number;
          tmpls: {
            afmt: string;
            bafmt: string;
            bfont: string;
            bqfmt: string;
            bsize: number;
            did: null;
            id: number;
            name: string;
            ord: number;
            qfmt: string;
          }[];
          type: number;
          usn: number;
        }[];
      } | {
        error: null | string;
        result: {
          css: string;
          did: null;
          flds: {
            collapsed: boolean;
            description: string;
            excludeFromSearch: boolean;
            font: string;
            id: number;
            name: string;
            ord: number;
            plainText: boolean;
            preventDeletion: boolean;
            rtl: boolean;
            size: number;
            sticky: boolean;
            tag: null;
          }[];
          id: number;
          latexPost: string;
          latexPre: string;
          latexsvg: boolean;
          mod: number;
          name: string;
          originalStockKind: number;
          req: Array<[number, string, number[]]>;
          sortf: number;
          tmpls: {
            afmt: string;
            bafmt: string;
            bfont: string;
            bqfmt: string;
            bsize: number;
            did: null;
            id: number;
            name: string;
            ord: number;
            qfmt: string;
          }[];
          type: number;
          usn: number;
        }[];
      } | {
        error: null | string;
        result: Record<string, {
          font: string;
          size: number;
        }>;
      } | {
        error: null | string;
        result: Record<string, [string[], string[]]>;
      } | {
        error: null | string;
        result: {
          css: string;
        };
      } | {
        error: null | string;
        result: Record<string, {
          [key: string]: string;
          Back: string;
          Front: string;
        }>;
      } | {
        error: null | string;
        result: number | null;
      } | {
        error: null | string;
        result: (string | null)[] | null;
      } | {
        error: null | string;
        result: ({
          canAdd: false;
          error: string;
        } | {
          canAdd: true;
        })[];
      } | {
        error: null | string;
        result: {
          cards: number[];
          fields: Record<string, {
            order: number;
            value: string;
          }>;
          mod: number;
          modelName: string;
          noteId: number;
          profile: string;
          tags: string[];
        }[];
      } | {
        error: null | string;
        result: {
          mod: number;
          noteId: number;
        }[];
      } | {
        error: null | string;
        result: [reviewTime: number, cardID: number, usn: number, buttonPressed: number, newInterval: number, previousInterval: number, newFactor: number, reviewDuration: number, reviewType: number][];
      } | {
        error: null | string;
        result: [string, number][];
      } | {
        error: null | string;
        result: Record<string, {
          ease: number;
          factor: number;
          id: number;
          ivl: number;
          lastIvl: number;
          time: number;
          type: number;
          usn: number;
        }[]>;
      } | {
        error: null | string;
        result: Requests["response"];
      })[];
    } | {
      error: null | string;
      result: {
        permission: "denied";
      } | {
        permission: "granted";
        requireApiKey: boolean;
        version: boolean;
      };
    } | {
      error: null | string;
      result: {
        css: string;
        did: null;
        flds: {
          collapsed: boolean;
          description: string;
          excludeFromSearch: boolean;
          font: string;
          id: number;
          name: string;
          ord: number;
          plainText: boolean;
          preventDeletion: boolean;
          rtl: boolean;
          size: number;
          sticky: boolean;
          tag: null;
        }[];
        id: number;
        latexPost: string;
        latexPre: string;
        latexsvg: boolean;
        mod: number;
        name: string;
        originalStockKind: number;
        req: Array<[number, string, number[]]>;
        sortf: number;
        tmpls: {
          afmt: string;
          bafmt: string;
          bfont: string;
          bqfmt: string;
          bsize: number;
          did: null;
          id: number;
          name: string;
          ord: number;
          qfmt: string;
        }[];
        type: number;
        usn: number;
      };
    } | {
      error: null | string;
      result: {
        css: string;
        did: null;
        flds: {
          collapsed: boolean;
          description: string;
          excludeFromSearch: boolean;
          font: string;
          id: number;
          name: string;
          ord: number;
          plainText: boolean;
          preventDeletion: boolean;
          rtl: boolean;
          size: number;
          sticky: boolean;
          tag: null;
        }[];
        id: number;
        latexPost: string;
        latexPre: string;
        latexsvg: boolean;
        mod: number;
        name: string;
        originalStockKind: number;
        req: Array<[number, string, number[]]>;
        sortf: number;
        tmpls: {
          afmt: string;
          bafmt: string;
          bfont: string;
          bqfmt: string;
          bsize: number;
          did: null;
          id: number;
          name: string;
          ord: number;
          qfmt: string;
        }[];
        type: number;
        usn: number;
      }[];
    } | {
      error: null | string;
      result: {
        css: string;
        did: null;
        flds: {
          collapsed: boolean;
          description: string;
          excludeFromSearch: boolean;
          font: string;
          id: number;
          name: string;
          ord: number;
          plainText: boolean;
          preventDeletion: boolean;
          rtl: boolean;
          size: number;
          sticky: boolean;
          tag: null;
        }[];
        id: number;
        latexPost: string;
        latexPre: string;
        latexsvg: boolean;
        mod: number;
        name: string;
        originalStockKind: number;
        req: Array<[number, string, number[]]>;
        sortf: number;
        tmpls: {
          afmt: string;
          bafmt: string;
          bfont: string;
          bqfmt: string;
          bsize: number;
          did: null;
          id: number;
          name: string;
          ord: number;
          qfmt: string;
        }[];
        type: number;
        usn: number;
      }[];
    } | {
      error: null | string;
      result: Record<string, {
        font: string;
        size: number;
      }>;
    } | {
      error: null | string;
      result: Record<string, [string[], string[]]>;
    } | {
      error: null | string;
      result: {
        css: string;
      };
    } | {
      error: null | string;
      result: Record<string, {
        [key: string]: string;
        Back: string;
        Front: string;
      }>;
    } | {
      error: null | string;
      result: number | null;
    } | {
      error: null | string;
      result: (string | null)[] | null;
    } | {
      error: null | string;
      result: ({
        canAdd: false;
        error: string;
      } | {
        canAdd: true;
      })[];
    } | {
      error: null | string;
      result: {
        cards: number[];
        fields: Record<string, {
          order: number;
          value: string;
        }>;
        mod: number;
        modelName: string;
        noteId: number;
        profile: string;
        tags: string[];
      }[];
    } | {
      error: null | string;
      result: {
        mod: number;
        noteId: number;
      }[];
    } | {
      error: null | string;
      result: [reviewTime: number, cardID: number, usn: number, buttonPressed: number, newInterval: number, previousInterval: number, newFactor: number, reviewDuration: number, reviewType: number][];
    } | {
      error: null | string;
      result: [string, number][];
    } | {
      error: null | string;
      result: Record<string, {
        ease: number;
        factor: number;
        id: number;
        ivl: number;
        lastIvl: number;
        time: number;
        type: number;
        usn: number;
      }[]>;
    } | {
      error: null | string;
      result: Requests["response"];
    })[]>;
    /**
     * Tells `anki` to reload all data from the database.
     */
    reloadCollection: () => Promise<null>;
    /**
     * Requests permission to use the API exposed by this plugin. This method
     * does not require the API key, and is the only one that accepts requests
     * from any origin; the other methods only accept requests from trusted
     * origins, which are listed under `webCorsOriginList` in the add-on config.
     * `localhost` is trusted by default.
     *
     * Calling this method from an untrusted origin will display a popup in Anki
     * asking the user whether they want to allow your origin to use the API;
     * calls from trusted origins will return the result without displaying the
     * popup. When denying permission, the user may also choose to ignore
     * further permission requests from that origin. These origins end up in the
     * `ignoreOriginList`, editable via the add-on config.
     *
     * The result always contains the `permission` field, which in turn contains
     * either the string `granted` or `denied`, corresponding to whether your
     * origin is trusted. If your origin is trusted, the fields `requireApiKey`
     * (true if required) and `version` will also be returned.
     *
     * This should be the first call you make to make sure that your application
     * and AnkiConnect are able to communicate properly with each other. New
     * versions of AnkiConnect are backwards compatible; as long as you are
     * using actions which are available in the reported AnkiConnect version or
     * earlier, everything should work fine.
     */
    requestPermission: () => Promise<{
      permission: "denied";
    } | {
      permission: "granted";
      requireApiKey: boolean;
      version: boolean;
    }>;
    /**
     * Synchronizes the local Anki collections with AnkiWeb.
     */
    sync: () => Promise<null>;
    /**
     * Gets the version of the API exposed by this plugin. Currently versions
     * `1` through `6` are defined.
     */
    version: () => Promise<number>;
  };
  /**
   * **Model Actions**
   *
   * [Documentation](https://git.sr.ht/~foosoft/anki-connect/tree/25.11.9.0/item/README.md#model-actions)
   */
  readonly model: {
    /**
     * Creates a new model to be used in Anki. User must provide the
     * `modelName`, `inOrderFields` and `cardTemplates` to be used in the model.
     * There are optional fields `css` and `isCloze`. If not specified, `css`
     * will use the default Anki css and `isCloze` will be equal to `false`. If
     * `isCloze` is `true` then model will be created as Cloze.
     *
     * Optionally the `Name` field can be provided for each entry of
     * `cardTemplates`. By default the card names will be `Card 1`, `Card 2`,
     * and so on.
     */
    createModel: (params: {
      cardTemplates: Array<{
        [key: string]: string;
        Back: string;
        Front: string;
      }>;
      css?: string;
      inOrderFields: string[];
      isCloze?: boolean;
      modelName: string;
    }) => Promise<{
      css: string;
      did: null;
      flds: {
        collapsed: boolean;
        description: string;
        excludeFromSearch: boolean;
        font: string;
        id: number;
        name: string;
        ord: number;
        plainText: boolean;
        preventDeletion: boolean;
        rtl: boolean;
        size: number;
        sticky: boolean;
        tag: null;
      }[];
      id: number;
      latexPost: string;
      latexPre: string;
      latexsvg: boolean;
      mod: number;
      name: string;
      originalStockKind: number;
      req: Array<[number, string, number[]]>;
      sortf: number;
      tmpls: {
        afmt: string;
        bafmt: string;
        bfont: string;
        bqfmt: string;
        bsize: number;
        did: null;
        id: number;
        name: string;
        ord: number;
        qfmt: string;
      }[];
      type: number;
      usn: number;
    }>;
    /**
     * Find and replace string in existing model by model name. Customize to
     * replace in front, back or css by setting to `true`/`false`.
     */
    findAndReplaceInModels: (params: {
      model: {
        back: boolean;
        css: boolean;
        fieldText: string;
        front: boolean;
        modelName: string;
        replaceText: string;
      };
    }) => Promise<number>;
    /**
     * Gets a list of models for the provided model IDs from the current user.
     */
    findModelsById: (params: {
      modelIds: number[];
    }) => Promise<{
      css: string;
      did: null;
      flds: {
        collapsed: boolean;
        description: string;
        excludeFromSearch: boolean;
        font: string;
        id: number;
        name: string;
        ord: number;
        plainText: boolean;
        preventDeletion: boolean;
        rtl: boolean;
        size: number;
        sticky: boolean;
        tag: null;
      }[];
      id: number;
      latexPost: string;
      latexPre: string;
      latexsvg: boolean;
      mod: number;
      name: string;
      originalStockKind: number;
      req: Array<[number, string, number[]]>;
      sortf: number;
      tmpls: {
        afmt: string;
        bafmt: string;
        bfont: string;
        bqfmt: string;
        bsize: number;
        did: null;
        id: number;
        name: string;
        ord: number;
        qfmt: string;
      }[];
      type: number;
      usn: number;
    }[]>;
    /**
     * Gets a list of models for the provided model names from the current user.
     */
    findModelsByName: (params: {
      modelNames: string[];
    }) => Promise<{
      css: string;
      did: null;
      flds: {
        collapsed: boolean;
        description: string;
        excludeFromSearch: boolean;
        font: string;
        id: number;
        name: string;
        ord: number;
        plainText: boolean;
        preventDeletion: boolean;
        rtl: boolean;
        size: number;
        sticky: boolean;
        tag: null;
      }[];
      id: number;
      latexPost: string;
      latexPre: string;
      latexsvg: boolean;
      mod: number;
      name: string;
      originalStockKind: number;
      req: Array<[number, string, number[]]>;
      sortf: number;
      tmpls: {
        afmt: string;
        bafmt: string;
        bfont: string;
        bqfmt: string;
        bsize: number;
        did: null;
        id: number;
        name: string;
        ord: number;
        qfmt: string;
      }[];
      type: number;
      usn: number;
    }[]>;
    /**
     * Creates a new field within a given model.
     *
     * Optionally, the `index` value can be provided, which works exactly the
     * same as the index in `modelFieldReposition`. By default, the field is
     * added to the end of the field list.
     */
    modelFieldAdd: (params: {
      fieldName: string;
      index: number;
      modelName: string;
    }) => Promise<null>;
    /**
     * Gets the complete list of field descriptions (the text seen in the gui
     * editor when a field is empty) for the provided model name.
     */
    modelFieldDescriptions: (params: {
      description: string;
      fieldName: string;
      modelName: string;
    }) => Promise<boolean>;
    /**
     * Gets the complete list of fonts along with their font sizes.
     */
    modelFieldFonts: (params: {
      modelName: string;
    }) => Promise<Record<string, {
      font: string;
      size: number;
    }>>;
    /**
     * Gets the complete list of field names for the provided model name.
     */
    modelFieldNames: (params: {
      modelName: string;
    }) => Promise<string[]>;
    /**
     * Deletes a field within a given model.
     */
    modelFieldRemove: (params: {
      fieldName: string;
      modelName: string;
    }) => Promise<null>;
    /**
     * Rename the field name of a given model.
     */
    modelFieldRename: (params: {
      modelName: string;
      newFieldName: string;
      oldFieldName: string;
    }) => Promise<null>;
    /**
     * Reposition the field within the field list of a given model.
     *
     * The value of `index` starts at 0. For example, an `index` of `0` puts the
     * field in the first position, and an `index` of `2` puts the field in the
     * third position.
     */
    modelFieldReposition: (params: {
      fieldName: string;
      index: number;
      modelName: string;
    }) => Promise<null>;
    /**
     * Sets the description (the text seen in the gui editor when a field is
     * empty) for a field within a given model.
     *
     * Older versions of Anki (2.1.49 and below) do not have field descriptions.
     * In that case, this will return with `false`.
     */
    modelFieldSetDescription: (params: {
      fieldName: string;
      index: number;
      modelName: string;
    }) => Promise<null>;
    /**
     * Sets the font for a field within a given model.
     */
    modelFieldSetFont: (params: {
      fieldName: string;
      font: string;
      modelName: string;
    }) => Promise<null>;
    /**
     * Sets the font size for a field within a given model.
     */
    modelFieldSetFontSize: (params: {
      fieldName: string;
      fontSize: number;
      modelName: string;
    }) => Promise<null>;
    /**
     * Returns an object indicating the fields on the question and answer side
     * of each card template for the given model name. The question side is
     * given first in each array.
     */
    modelFieldsOnTemplates: (params: {
      modelName: string;
    }) => Promise<Record<string, [string[], string[]]>>;
    /**
     * Gets the complete list of model names for the current user.
     */
    modelNames: () => Promise<string[]>;
    /**
     * Gets the complete list of model names and their corresponding IDs for the
     * current user.
     */
    modelNamesAndIds: () => Promise<Record<string, number>>;
    /**
     * Gets the CSS styling for the provided model by name.
     */
    modelStyling: (params: {
      modelName: string;
    }) => Promise<{
      css: string;
    }>;
    /**
     * Adds a template to an existing model by name. If you want to update an
     * existing template, use `updateModelTemplates`.
     */
    modelTemplateAdd: (params: {
      modelName: string;
      template: {
        [key: string]: string;
        Back: string;
        Front: string;
      };
    }) => Promise<null>;
    /**
     * Removes a template from an existing model.
     */
    modelTemplateRemove: (params: {
      modelName: string;
      templateName: string;
    }) => Promise<null>;
    /**
     * Renames a template in an existing model.
     */
    modelTemplateRename: (params: {
      modelName: string;
      newTemplateName: string;
      oldTemplateName: string;
    }) => Promise<null>;
    /**
     * Repositions a template in an existing model.
     */
    modelTemplateReposition: (params: {
      index: number;
      modelName: string;
      templateName: string;
    }) => Promise<null>;
    /**
     * Returns an object indicating the template content for each card connected
     * to the provided model by name.
     *
     * The value of `index` starts at 0. For example, an `index` of `0` puts the
     * template in the first position, and an `index` of `2` puts the template
     * in the third position.
     */
    modelTemplates: (params: {
      modelName: string;
    }) => Promise<Record<string, {
      [key: string]: string;
      Back: string;
      Front: string;
    }>>;
    /**
     * Modify the CSS styling of an existing model by name.
     */
    updateModelStyling: (params: {
      model: {
        css: string;
        name: string;
      };
    }) => Promise<null>;
    /**
     * Modify the templates of an existing model by name. Only specifies cards
     * and specified sides will be modified. If an existing card or side is not
     * included in the request, it will be left unchanged.
     */
    updateModelTemplates: (params: {
      model: {
        name: string;
        templates: Record<string, {
          Back?: string;
          Front?: string;
        }>;
      };
    }) => Promise<null>;
  };
  /**
   * **Note Actions**
   *
   * [Documentation](https://git.sr.ht/~foosoft/anki-connect/tree/25.11.9.0/item/README.md#note-actions)
   */
  readonly note: {
    /**
     * Creates a note using the given deck and model, with the provided field
     * values and tags. Returns the identifier of the created note created on
     * success, and `null` on failure.
     *
     * AnkiConnect can download audio, video, and picture files and embed them
     * in newly created notes. The corresponding `audio`, `video`, and `picture`
     * note members are optional and can be omitted. If you choose to include
     * any of them, they should contain a single object or an array of objects
     * with the mandatory `filename` field and one of `data`, `path` or `url`.
     * Refer to the documentation of `storeMediaFile` for an explanation of
     * these fields. The `skipHash` field can be optionally provided to skip the
     * inclusion of files with an MD5 hash that matches the provided value. This
     * is useful for avoiding the saving of error pages and stub files. The
     * `fields` member is a list of field names to which the inserted media
     * should be appended to. It can be omitted if this isn't required. The
     * `allowDuplicate` member inside `options` group can be set to true to
     * enable adding duplicate cards. Normally duplicate cards can not be added
     * and trigger exception.
     *
     * The `duplicateScope` member inside `options` can be used to specify the
     * scope for which duplicates are checked. A value of `"deck"` will only
     * check for duplicates in the target deck; any other value will check the
     * entire collection.
     *
     * The `duplicateScopeOptions` object can be used to specify some additional
     * settings:
     *
     * - `duplicateScopeOptions.deckName` will specify which deck to use for
     *   checking duplicates in. If undefined or `null`, the target deck will be
     *   used.
     * - `duplicateScopeOptions.checkChildren` will change whether or not
     *   duplicate cards are checked in child decks. The default value is
     *   `false`.
     * - `duplicateScopeOptions.checkAllModels` specifies whether duplicate checks
     *   are performed across all note types. The default value is `false`.
     */
    addNote: (params: {
      note: Note & {
        options?: {
          allowDuplicate?: boolean;
          duplicateScope?: "deck" | (string & {});
          duplicateScopeOptions?: {
            checkAllModels?: boolean;
            checkChildren?: boolean;
            deckName?: null | string;
          };
        };
      };
    }) => Promise<number | null>;
    /**
     * Creates multiple notes using the given deck and model, with the provided
     * field values and tags. Returns an array of identifiers of the created
     * notes. In the event of any errors, all errors are gathered and returned.
     *
     * Please see the documentation for `addNote` for an explanation of objects
     * in the `notes` array.
     */
    addNotes: (params: {
      notes: (Note & {
        options?: {
          allowDuplicate?: boolean;
          duplicateScope?: "deck" | (string & {});
          duplicateScopeOptions?: {
            checkAllModels?: boolean;
            checkChildren?: boolean;
            deckName?: null | string;
          };
        };
      })[];
    }) => Promise<(string | null)[] | null>;
    /**
     * Adds tags to notes by note ID.
     */
    addTags: (params: {
      notes: number[];
      tags: string;
    }) => Promise<null>;
    /**
     * Accepts an array of objects which define parameters for candidate notes
     * (see `addNote`) and returns an array of booleans indicating whether or
     * not the parameters at the corresponding index could be used to create a
     * new note.
     */
    canAddNotes: (params: {
      notes: (Note & {
        options?: {
          allowDuplicate?: boolean;
          duplicateScope?: "deck" | (string & {});
          duplicateScopeOptions?: {
            checkAllModels?: boolean;
            checkChildren?: boolean;
            deckName?: null | string;
          };
        };
      })[];
    }) => Promise<boolean[]>;
    /**
     * Accepts an array of objects which define parameters for candidate notes
     * (see `addNote`) and returns an array of objects with fields `canAdd` and
     * `error`.
     *
     * - `canAdd` indicates whether or not the parameters at the corresponding
     *   index could be used to create a new note.
     * - `error` contains an explanation of why a note cannot be added.
     */
    canAddNotesWithErrorDetail: (params: {
      notes: (Note & {
        options?: {
          allowDuplicate?: boolean;
          duplicateScope?: "deck" | (string & {});
          duplicateScopeOptions?: {
            checkAllModels?: boolean;
            checkChildren?: boolean;
            deckName?: null | string;
          };
        };
      })[];
    }) => Promise<({
      canAdd: false;
      error: string;
    } | {
      canAdd: true;
    })[]>;
    /**
     * Clears all the unused tags in the notes for the current user.
     */
    clearUnusedTags: () => Promise<string[]>;
    /**
     * Deletes notes with the given ids. If a note has several cards associated
     * with it, all associated cards will be deleted.
     */
    deleteNotes: (params: {
      notes: number[];
    }) => Promise<null>;
    /**
     * Returns an array of note IDs for a given query. Query syntax is
     * [documented here](https://docs.ankiweb.net/searching.html).
     */
    findNotes: (params: {
      query: string;
    }) => Promise<number[]>;
    /**
     * Get a note's tags by note ID.
     */
    getNoteTags: (params: {
      note: number;
    }) => Promise<string[]>;
    /**
     * Gets the complete list of tags for the current user.
     */
    getTags: () => Promise<string[]>;
    /**
     * Returns a list of objects containing for each note ID the note fields,
     * tags, note type, modification time, the cards belonging to the note and
     * the profile where the note was created.
     */
    notesInfo: (params: {
      notes: number[];
    }) => Promise<{
      cards: number[];
      fields: Record<string, {
        order: number;
        value: string;
      }>;
      mod: number;
      modelName: string;
      noteId: number;
      profile: string;
      tags: string[];
    }[]>;
    /**
     * Returns a list of objects containing for each note ID the modification
     * time.
     */
    notesModTime: (params: {
      notes: number[];
    }) => Promise<{
      cards: number[];
      fields: Record<string, {
        order: number;
        value: string;
      }>;
      mod: number;
      modelName: string;
      noteId: number;
      profile: string;
      tags: string[];
    }[]>;
    /**
     * Removes all the empty notes for the current user.
     */
    removeEmptyNotes: () => Promise<null>;
    /**
     * Remove tags from notes by note ID.
     */
    removeTags: (params: {
      notes: number[];
      tags: string;
    }) => Promise<null>;
    /**
     * Replace tags in notes by note ID.
     */
    replaceTags: (params: {
      notes: number[];
      replace_with_tag: string;
      tag_to_replace: string;
    }) => Promise<null>;
    /**
     * Replace tags in all the notes for the current user.
     */
    replaceTagsInAllNotes: (params: {
      replace_with_tag: string;
      tag_to_replace: string;
    }) => Promise<null>;
    /**
     * Modify the fields and/or tags of an existing note. In other words,
     * combines `updateNoteFields` and `updateNoteTags`. Please see their
     * documentation for an explanation of all properties.
     *
     * Either `fields` or `tags` property can be omitted without affecting the
     * other. Thus valid requests to `updateNoteFields` also work with
     * `updateNote`. The note must have the `fields` property in order to update
     * the optional audio, video, or picture objects.
     *
     * If neither `fields` nor `tags` are provided, the method will fail. Fields
     * are updated first and are not rolled back if updating tags fails. Tags
     * are not updated if updating fields fails.
     *
     * > [!WARNING] You must not be viewing the note that you are updating on your
     * > Anki browser, otherwise the fields will not update. See [this
     * > issue](https://github.com/FooSoft/anki-connect/issues/82) for further
     * > details.
     */
    updateNote: (params: {
      note: {
        audio?: {
          data?: string;
          fields?: string[];
          filename: string;
          path?: string;
          skipHash?: string;
          url?: string;
        }[];
        fields: Record<string, string>;
        id: number;
        picture?: {
          data?: string;
          fields?: string[];
          filename: string;
          path?: string;
          skipHash?: string;
          url?: string;
        }[];
        tags?: string[];
        video?: {
          data?: string;
          fields?: string[];
          filename: string;
          path?: string;
          skipHash?: string;
          url?: string;
        }[];
      } | {
        fields?: Record<string, string>;
        id: number;
        tags: string[];
      };
    }) => Promise<null>;
    /**
     * Modify the fields of an existing note. You can also include audio, video,
     * or picture files which will be added to the note with an optional
     * `audio`, `video`, or `picture` property. Please see the documentation for
     * `addNote` for an explanation of objects in the `audio`, `video`, or
     * `picture` array.
     *
     * > [!WARNING] You must not be viewing the note that you are updating on your
     * > Anki browser, otherwise the fields will not update. See [this
     * > issue](https://github.com/FooSoft/anki-connect/issues/82) for further
     * > details.
     */
    updateNoteFields: (params: {
      note: {
        audio?: {
          data?: string;
          fields?: string[];
          filename: string;
          path?: string;
          skipHash?: string;
          url?: string;
        }[];
        fields: Record<string, string>;
        id: number;
        picture?: {
          data?: string;
          fields?: string[];
          filename: string;
          path?: string;
          skipHash?: string;
          url?: string;
        }[];
        video?: {
          data?: string;
          fields?: string[];
          filename: string;
          path?: string;
          skipHash?: string;
          url?: string;
        }[];
      };
    }) => Promise<null>;
    /**
     * Update the model, fields, and tags of an existing note. This allows you
     * to change the note's model, update its fields with new content, and set
     * new tags.
     */
    updateNoteModel: (params: {
      note: {
        fields: Record<string, string>;
        id: number;
        modelName: string;
        tags: string[];
      };
    }) => Promise<null>;
    /**
     * Set a note's tags by note ID. Old tags will be removed.
     */
    updateNoteTags: (params: {
      note: number;
      tags: string[];
    }) => Promise<null>;
  };
  /**
   * **Statistic Actions**
   *
   * [Documentation](https://git.sr.ht/~foosoft/anki-connect/tree/25.11.9.0/item/README.md#statistic-actions)
   */
  readonly statistic: {
    /**
     * Requests all card reviews for a specified deck after a certain time.
     * `startID` is the latest unix time not included in the result. Returns a
     * list of 9-tuples `(reviewTime, cardID, usn, buttonPressed, newInterval,
     * previousInterval, newFactor, reviewDuration, reviewType)`.
     */
    cardReviews: (params: {
      deck: string;
      startID: number;
    }) => Promise<[reviewTime: number, cardID: number, usn: number, buttonPressed: number, newInterval: number, previousInterval: number, newFactor: number, reviewDuration: number, reviewType: number][]>;
    /**
     * Gets the collection statistics report.
     */
    getCollectionStatsHTML: (params: {
      wholeCollection: boolean;
    }) => Promise<string>;
    /**
     * Returns the unix time of the latest review for the given deck. 0 if no
     * review has ever been made for the deck.
     */
    getLatestReviewID: (params: {
      deck: string;
    }) => Promise<number>;
    /**
     * Gets the number of cards reviewed as a list of pairs of (`dateString`,
     * `number`).
     */
    getNumCardsReviewedByDay: () => Promise<[string, number][]>;
    /**
     * Gets the count of cards that have been reviewed in the current day. (With
     * day start time as configured by user in Anki).
     */
    getNumCardsReviewedToday: () => Promise<number>;
    /**
     * Requests all card reviews for each card ID. Returns a dictionary mapping
     * each card ID to a list of dictionaries of the format:
     *
     * ```ts
     * {
     *    "id": reviewTime,
     *    "usn": usn,
     *    "ease": buttonPressed,
     *    "ivl": newInterval,
     *    "lastIvl": previousInterval,
     *    "factor": newFactor,
     *    "time": reviewDuration,
     *    "type": reviewType,
     * }
     * ```
     *
     * The reason why these key values are used instead of the more descriptive
     * counterparts is because these are the exact key values used in Anki's
     * database.
     */
    getReviewsOfCards: (params: {
      cards: string[];
    }) => Promise<Record<string, {
      ease: number;
      factor: number;
      id: number;
      ivl: number;
      lastIvl: number;
      time: number;
      type: number;
      usn: number;
    }[]>>;
    /**
     * Inserts the given reviews into the database. Required format: list of
     * 9-tuples `(reviewTime, cardID, usn, buttonPressed, newInterval,
     * previousInterval, newFactor, reviewDuration, reviewType)`.
     */
    insertReviews: (params: {
      reviews: [reviewTime: number, cardID: number, usn: number, buttonPressed: number, newInterval: number, previousInterval: number, newFactor: number, reviewDuration: number, reviewType: number][];
    }) => Promise<null>;
  };
  private readonly autoLaunch;
  private readonly fetchAdapter;
  private readonly host;
  private readonly key;
  private readonly port;
  private readonly version;
  constructor(options?: Partial<YankiConnectOptions>);
  /**
   * Directly invoke the Anki Connect API.
   *
   * [Documentation](https://git.sr.ht/~foosoft/anki-connect/tree/25.11.9.0/item/README.md)
   *
   * Primarily for internal use, since the client provides a more convenient
   * methods on its class, e.g. instead of:
   *
   * ```ts
   * const client = new AnkiConnectClient()
   * const response = await client.invoke('version')
   * ```
   *
   * You can use:
   *
   * ```ts
   * const client = new AnkiConnectClient()
   * const result = await client.miscellaneous.version()
   * ```
   */
  invoke<T extends ActionsWithoutParams>(action: T): Promise<ResponseForAction<T>>;
  invoke<T extends ActionsWithParams>(action: T, params: ParamsForAction<T>): Promise<ResponseForAction<T>>;
  /**
   * Factory for creating convenience functions for each action. Overload for
   * actions with / without params
   *
   * Note that the generated function returns the response's Result field! Any
   * errors, even from Anki, will throw.
   */
  private build;
}
//#endregion
export { YankiConnect, type YankiConnectOptions, type YankiFetchAdapter, type ParamsForAction as YankiParamsForAction, type ResponseForAction as YankiResponseForAction, defaultYankiConnectOptions };