Insurgently

Changelog

Changes to Library Hub's API, by version.

agents/CHANGELOG.md
title: Changelog
built: 2026-10-30
source: api/CHANGELOG.md
html: https://insurgently.com/projects/library-hub/technical/agents/CHANGELOG
Index of these files: llms.txt

Changes to Library Hub's API, by version. Within 0.x the API only adds and deprecates, and removes at 1.0; a change in behavior is marked.

0.9.0

Served by Library Hub 0.1.0 and later; the first version published as a package (0.8.0 was never published). Everything new is an addition, except the changes marked below.

  • listBooks('all'): every book in Calibre, by id.
  • BookSummary.context: what the book is about, as plain text, from the note's context field, else Calibre's comments.
  • BookChapters.outline (and so BookText.outline): whether the chapters follow the book's own structure, an EPUB's files or a PDF's outline. False for a PDF cut into even parts. Before, only the warning text said so.
  • Changed: bookText and bookChapters give every chapter of an EPUB: past 30 they're no longer merged into their parts (the chapter notes still merge them, and openBook's chapter number counts the notes' chapters, so open a chapter at its location). A file several contents entries point into is split at their anchors, each such chapter located file#anchor; a file no entry claims, with more than a page heading's text, is a chapter of its own; and contents entries are found when the NCX sits in another folder than the OPF. These chapter rules don't change the whole text (reading it with foliate-js, below, does, once).
  • Changed: bookText and bookChapters read EPUB, AZW3 and MOBI files with foliate-js, the parser Library Hub's reader already shows them with, instead of Library Hub's own EPUB reading. An EPUB's contents come from its nav document or its NCX, as foliate-js gives them; HTML entities in a contents file no longer lose the contents. The whole text keeps its paragraphs and blocks as blank lines, and a line break (<br>) is now a single line break; spaces next to a paragraph break are gone and every HTML entity is decoded. So every EPUB's hash changes once, and offsets may move a little; a corpus re-reads the passages whose words changed.
  • Changed: a book with only an AZW3 or MOBI has its text read from that file as it is, with no conversion, with or without the Content Server: format is AZW3 or MOBI (BookChapters.format takes those two), and each chapter's location is the reader's own (kindle:pos:…, filepos:…, or a section's epubcfi(…)), which openBook opens. needs-conversion and { convert: true } now only matter for an AZW3 or MOBI that can't be read (DRM, a damaged file), and the message names the cause. openBook opens a book's AZW3 or MOBI when it has no EPUB, before its PDF. bookFile(book, 'EPUB', { convert: true }) still asks Calibre to make an EPUB.
  • Changed: with Calibre's Content Server off and a library folder set, bookFile, pdfText, bookText and bookChapters read a Calibre book's files straight from the library folder, read-only, instead of rejecting with server-off. Converting an AZW3 or MOBI still needs the server: bookFile with { convert: true } rejects with server-off, and bookText/bookChapters reject with needs-conversion when the book has a PDF (with convert, the PDF is read, with a warning) and with server-off when it has none. A file in a cloud-synced folder that isn't downloaded on this computer, or takes too long to download, rejects with server-error naming the file; a library file caught while Calibre is writing it is read again a few times, then rejects with busy. status().calibre in file mode now has files: true and says files and text are read from the library folder.
  • Changed: openBook at a quote, and a highlight finding its text again, match through @insurgently/text's fold: decomposed and precomposed accents, curly and straight quotes and apostrophes (with ʼ, ʻ, backticks and guillemets), soft hyphens, zero-width characters, Greek final sigma, Turkish İ, German ß, and hyphenated, closed or line-split words (well-known, well-\nknown, wellknown, OCR's ¬) now match each other; a quote never matches half a letter. Whitespace and quote marks are still ignored altogether. summarizeBook's chapter notes keep a quote found word for word by the same rules, so a quote a model typed with straight quotes is no longer dropped.
  • Changed: with Model Hub 0.13 or later, estimateSummary and estimateShelfFromDescription are priced by Model Hub's estimate(), each call as it would be sent with its reply cap: usd is the high end of its range (every call with a full reply), and text gives the range, "about $0.02–$0.09". When Model Hub can't price a call, usd is null and text says why. With Model Hub 0.12, both work as before: the input at the role's first model's listed price.

0.8.0

Never published as a package on its own: it ships inside 0.9.0.

  • bookText(book, { convert? }) and bookChapters(book, { convert? }): a book's text as chapters. Each chapter has n, title, a location that openBook lands on (OEBPS/c3.xhtml in an EPUB, chars a-b in a PDF), start and end in code points, and (from bookText) its text. A SHA-256 hash of the whole text changes only when the text does. EPUBs, AZW3 and MOBI through Calibre's conversion (asked first), and PDFs laid out, with their outline as chapters.
  • status(): whether Calibre's Content Server and the other providers answer, and what the library holds.
  • A BookRef wherever a book is named: listBooks, bookFile, pdfText, shelvesOf, addToShelf, removeFromShelf, createShelf's books, suggestShelves, estimateSummary, summarizeBook. Numbers work as before. bookFile and pdfText also read a book file in the vault.
  • New error codes: needs-conversion, declined, not-calibre, busy.
  • hasMethod(api, name), and getLibraryHub's opts.by and opts.for to name your plugin, and what it needs books for, in its messages.
  • LIBRARY_HUB_TOOLS is also at @insurgently/library-hub-api/tools. Import it from there: at the root it's deprecated, and goes at 1.0.
  • New error code needs-topic-map: the call works from what books are about (book vectors), which Library Hub no longer keeps; the Topic Map plugin serves it.
  • Changed: suggestShelves is served by Topic Map: with Topic Map's rankGroups it ranks the shelves by what the book and their books are about (score and match are Topic Map's score, because says it in words); without Topic Map, or with one that doesn't offer rankGroups yet, it rejects with needs-topic-map after checking its arguments, and with no-vectors when Topic Map hasn't indexed the book. The library-hub.suggest_shelves tool is offered to Model Hub only while Topic Map serves it.
  • Changed: shelfFromDescription and estimateShelfFromDescription find the books to read by their words: those that best match the description and its terms (title, authors and context, by a keyword ranking), and any naming a term. Before, the books nearest it by meaning. Neither rejects with no-vectors. With Topic Map's rankGroups there, the books it finds closest to the description in meaning are read too (Topic Map embeds the description); without it, no embedding is asked.
  • Changed: the shelf keys have new names. A shelf note's id is shelf_id (was collection_id); a book note's shelves are in shelves and its exclusions in shelves_exclude (were collections and collections_exclude); clusters and auto_shelves are gone, and rule shelves with them: the plugin moves old notes once, putting every book a rule shelf held in shelves. listShelves, shelfMembers, shelvesOf and the write operations name shelves by shelf_id as before and keep the keys to themselves; a plugin that reads book notes' frontmatter itself reads the new keys.
  • Changed: shelfBaseQuery gives list(shelves).contains(…) and the shelves_exclude test, with no rule and no older keys.
  • Changed: createShelf with a rule rejects with needs-topic-map. NewShelf.rule and ShelfInfo.rule are deprecated (rule is never set), until 1.0.
  • Changed: no-vectors now means Topic Map hasn't indexed the library, or the book, yet.
  • Changed: pdfText lays the page out: a line on its own line, a wider gap a blank line, a word broken at a line's end joined. Before, a page's pieces were joined by spaces. chars a-b offsets count in the new text.
  • The names from before the rename (getBooks, onBooksReady, BooksApi, BooksErrorCode, BooksTool, GetBooksResult and the BOOKS_* constants) still work, deprecated. Within 0.x the API only adds and deprecates; they go at 1.0.

0.7.0 and before

Not published as a package. Plugins copied api/index.ts from the repo; the plugin's own CHANGELOG lists what each version added.