/** * What a tab's colour is held as. * * The fingerprint is what makes a terminal entry verifiable: the name it is * keyed on is a slot the server reuses, so without an incarnation to compare * against there is no way to know whether the colour belongs to the terminal * now answering to that name. */ export interface IStoredColour { /** Index into the palette. */ colour: number; /** Fingerprint of the terminal incarnation the colour was chosen on. Absent * for a file path, which needs none, and for a terminal entry written before * the fingerprint existed or while the route was unreachable. */ fp?: string; } /** * One persisted value read back as a stored colour, or null when it is not one. * * localStorage is shared with every other script on the origin, is editable by * hand and outlives every version of this extension, so a value read out of it * is input rather than something this code is entitled to trust. An unchecked * value reaches `entry.colour` and `entry.fp` on every prune and every repaint, * where a null or a string throws and takes tab colouring down for that browser * until the key is cleared by hand. Anything that does not read back as a * colour is dropped silently: it is corrupt data, not a choice the user made. * * @param value - one entry exactly as `JSON.parse` returned it * @param paletteSize - how many colours the palette defines */ export declare function parseStoredColour(value: unknown, paletteSize: number): IStoredColour | null; /** * The key a tab's colour is persisted under, or null when the tab has no stable * identity. * * A file tab resolves to its path (the only true identity JupyterLab hands us), * a terminal to its session name. Everything else - launcher, settings - is * null: their widget ids (`launcher-0`) are a per-browser-session counter, so * the first launcher of every session is always `launcher-0` and a colour * stored under it paints every future first launcher (DEF-6). Callers still * colour such tabs, holding the colour on the widget title; it lasts as long * as the widget and is never stored. * * A path that begins with one of the storage prefixes is escaped with * `path:` plus a NUL sentinel, so a legal root-level file named `terminal:3` * is stored as `path:terminal:3` rather than as the key of terminal 3. * `path:` itself is escaped too. The sentinel is a NUL, which no file path can * contain, so the escaped form is impossible to produce as a raw path; the * earlier plain `path:` prefix was a legal path prefix and the two key spaces * overlapped. The escape belongs to the path branch only; terminal keys * remain `terminal:`. * * @param titleAttr - the tab's `title` attribute; files carry `Path: ` * @param terminalSessionName - the terminal's session name, or null if not a terminal */ export declare function stableTabId(titleAttr: string | null, terminalSessionName: string | null): string | null; /** * The current key for a stored id, rewriting the one legacy form the sentinel * must not be confused with. * * A 1.1.22 store held a file path verbatim, so a key beginning `path:` was the * file of that name. Read as a sentinel escape, it painted file `terminal:3` * when it meant file `path:terminal:3`, while a key `path:3` matched no tab at * all and its colour was lost. Rewriting at read time under the sentinel * recovers the file the key recorded; the next save writes the current form. * Applying it twice is a no-op: no legal path contains NUL, so a sentinel key * is already final. * * @param storedId - one key exactly as it was read from storage */ export declare function normaliseStoredTabId(storedId: string): string; /** The session name behind a stored id, or null when the id is a file path. */ export declare function terminalSessionName(tabId: string): string | null; /** * Stored ids whose terminal incarnation the server no longer vouches for. * * Terminal names are slots, not identities - terminado's * `_next_available_name` counts from 1 and returns the first name not in use - * so a closed terminal's name is handed to the next terminal created. A rule * built on the running list alone structurally cannot see that substitution: * the recycled name IS running, so the dead terminal's entry survives every * prune and its colour paints the new terminal (DEF-6, observed 2026-09-04 as a * fresh terminal rendering green). Only a per-incarnation fingerprint separates * the two. * * `fingerprints` null means the server could not be asked - an older server, or * the companion server extension disabled. There the running list is the only * evidence there is, so the pre-fingerprint rule stands unchanged; treating a * missing fingerprint as stale in that branch would wipe every stored terminal * colour on such a server. * * A file path is a real identity and is never returned by this. * * @param stored - every persisted entry, id to value * @param fingerprints - live session name to fingerprint, or null when unknown * @param liveNames - session names the server reports running */ export declare function staleTerminalIds(stored: Iterable, fingerprints: Record | null, liveNames: Iterable): string[];