github zeeyado/koassistant.koplugin v0.22.0

latest release: v0.22.1
3 hours ago

KOAssistant v0.22.0 Release Notes

Behavior changed in this release. Nothing starts a book's X-Ray on its own any more, and every first build asks first. Three settings were removed with that change: "Also Start X-Rays Automatically", "First Build for New Books" and "Offer Automatic X-Ray for New Books". If you had them on, see the first two bullets below. Existing X-Rays, chats, notebooks and API keys are not affected.

Your per-book data moved. Chats and per-book settings now live in the book's own .sdr folder in plugin files instead of inside KOReader's metadata.lua. The move happens automatically on first start and nothing is lost; details under Storage.


Spoiler Protection and X-Ray

Automation only continues what you started.

  • Nothing starts an X-Ray on its own. "Automatic X-Ray (all books)" now only keeps up to date the X-Rays you have already started; a book with no X-Ray is left alone. The settings that used to start one ("Also Start X-Rays Automatically", "First Build for New Books" and its coverage question, "Offer Automatic X-Ray for New Books") are gone. Stale values are ignored, nothing needs migrating.
  • Every first build asks first. The two ways to start a background X-Ray are the creation form's "In checkpoints, as I read (automatic)" pick and the per-book "Automatic X-Ray: On" switch. Both now say how many background requests they need right now and wait for Start; Cancel puts the switch back the way it was and nothing runs. (When nothing needs building right now, the switch just turns on.) A book left On while it was closed gets the same question the moment the first build would start, with "Cancel (turn Automatic X-Ray off)" as the way out. Books that already have an X-Ray keep being extended silently, which is what Automatic means.
  • Deleting an X-Ray now quiets automation for that book, so nothing re-asks or restarts behind you after a delete.
  • The Automatic X-Ray cooldown is cleared when a build chain finishes; a completed chain used to silently decline page-turn triggers for a whole cooldown.

New: depth.

  • Depth of New X-Rays: Light / Standard / Deep. Light is one line per entry and only recurring figures and turning points; Standard (the default, unchanged from before) is a few sentences per entry; Deep is longer entries with richer connections. Set the default in Settings > Reading & Library > X-Ray > Depth of New X-Rays, per book in Book Settings > X-Ray > New X-Ray depth, or from the creation form. It applies to creates and rebuilds; checkpoints and updates keep the depth the X-Ray was started with.

Categories.

  • Presets renamed and re-cut: All categories, Characters and story (people, timeline), Reference (everything except the timeline), Characters only. The timeline turned out to be the single heaviest block of an X-Ray, so "Reference" is now the cheap pick and cost lives on the depth dial instead. The picker separates presets from picking categories one by one.

Creation form and checkpoints.

  • Spacing, categories and depth sit on one small options row above the action buttons, each button showing its current value, and the categories and depth pickers open on the book tab from there and from Book Settings. On a plain extend the categories and depth buttons show what the X-Ray was started with (they are locked to it), not the current default.
  • A one-step checkpoint plan stays pickable instead of disappearing, and the 100%-covered "Rebuild X-Ray..." row opens the rebuild form directly (no more deleting first).
  • A build that only covers up to your position no longer spends a request on a separate introduction it would immediately supersede.
  • The next checkpoint starts building only after the current one installs, and builds from the live copy, so entity renames and merges you made carry forward.
  • A checkpoint installs only once you actually reach its coverage (it used to install a hair early).

Entity cards and marking.

  • Upcoming entities reveal in stages. An entity known only from the checkpoint built ahead of you now shows name and category first, one tap adds the first sentence, and another opens the full entry behind the usual spoiler confirmation. Two new settings: Upcoming Entity Cards (name only / first sentence right away) and Card Shows (first sentence only / full entry, for entities already in your installed X-Ray). Both can be overridden per book. When the tap landed on an alias, the card stays at name only even with "first sentence right away", since the sentence would give away which entry the alias belongs to.
  • The peek reads one checkpoint, never a later one: the ahead card now uses the lowest built checkpoint that reaches your position, so an alias folded in at 100% cannot reveal itself on sight.
  • Tapping a marked alias opens the card on the words you tapped, not on the entry name (which gave the link away).
  • A name inside another entity's longer name now counts as the longer entity's mention everywhere: marks, mention lists, chapter appearances and counts.
  • Names whose own edge is punctuation ("D.B.", "Jr.") are marked again.
  • The first-sentence cut on cards handles initials, titles, CJK sentence ends and the Arabic question mark instead of stopping at the first period.
  • The card no longer shows the whole entry when the first sentence ends in a non-breaking space, or when the next word starts lowercase after an ordinary word (a name like "van" or "de"); only short abbreviations such as "vs." still hold the sentence open. This is why some cards were cut and others were not.

Other X-Ray.

  • One more JSON repair: a key that arrives missing its opening quote is restored, so a long build is not lost to it (the same family of fixes as v0.21.2).
  • Artifact caches now record the request's token usage, shown on the artifact viewer's Info button.
  • Section runs of Counterarguments now cache and browse like the other section artifacts.
  • The X-Ray browser's root Mentions view defaults to the whole book once the book is marked Finished.
  • A typeless non-fiction X-Ray is no longer read as a fiction one (it used to render every category empty).

Book Groups and Cross-Book X-Ray (#90)

The headline of this cycle: in a group, an X-Ray lookup answers from the whole group, not just the open book, and every group now has its own page and its own settings.

  • Lookups reach the group. Tapping a marked word, an exact dictionary or highlight match, an entity card, and the X-Ray browser's search all fall back, in order, to this book's carried list and then to the group's other X-Rays, nearest book first. Cards and rows name their source ("Carried from Title", "From Title's X-Ray"), and a hit from another book offers "Open in Title's X-Ray" and "Add to this book's carried list".
  • The browser's search results fold the group in as "From Title" groups, under the carried entries, with a plain "Nothing in the earlier books either" (or "Nothing in the other books of the group either") when there is nothing anywhere. No second tap.
  • Carried lists keep themselves up to date. Editing a group (adding, removing, reordering, changing its kind) or writing any of its X-Rays re-seeds the members' carried lists in the background. Removing a carried entry is remembered, so it does not come back.
  • Later volumes stay closed. In an ordered series a lookup only looks past a book once that book is read (marked Finished, or read to its last page) or its own spoiler protection is off. Volume 1 unread and protected keeps volumes 2 and 3 out of reach, whatever their own settings say. Passive marking, entity cards and matching selections never reach past that chain.
  • The reveal is one book at a time. When something is held back, the results list and the no-results dialog carry a row naming the next volume ("Search Title too (may contain spoilers)..."), the confirmation names it too, and each confirmation opens exactly one more book. Nothing sticks: every search starts from the chain again.
  • Project groups share in every direction between all members; plain groups share nothing.
  • The "add this as an alias of an existing entry" offer now also appears on books that have section X-Rays (it used to fall back to a bare message there).
  • Series suggestion sees edited metadata: a series typed into KOReader's own Book information editor now counts like one read from the file.
  • Installing a checkpoint no longer drops carried entries and aliases that existed only in the live copy.
  • The group jump is spoiler-safe. From an X-Ray entry, the "→ Group" popup lists a later volume that is still behind the spoiler chain as "(later in the series)" without checking whether the entity appears in it (knowing that a character returns is already a spoiler), and opens it only after the same confirmation the search reveal uses. From an entity page, the other book's entry opens as a read-only view over the page instead of switching X-Rays. Entity cards and pages also say where else in the group the entity appears ("Also in Title's X-Ray"), never naming a later volume the spoiler chain still holds back.

Group Hub and group settings.

  • Every group has a page. Main menu > Groups opens the Groups list: one row per group with its kind icon and "Kind · N books"; tap for the group's hub, hold to move, rename, change the kind or delete it, and the title-bar menu creates groups (blank, from a folder, from a collection, or with the open book) and sorts the list by name or by kind (a one-shot sort; you can still move groups by hand). The list itself also offers "New group from series ..." when the open book carries a series tag.
  • The Group Hub shows a group's action rows first (Group Settings, the X-Ray fold row, and a Series/Project/Group Chat/Action row that opens the library dialog with the members pre-selected), then the members in order (tap for a book's Book Hub, hold to move, open or remove it), then the add rows. Its title-bar menu carries the add flows, Kind, Rename and Delete; the up-arrow returns to the list. The Book Hub's Group row, the artifact viewers' "→ Group" button and the Quick Actions "Group Hub" utility all land on the book's hub (a chooser when it is in several groups); the X-Ray browser's own "→ Group" keeps opening the members popup, which has a "Group hub..." row. A Book Hub opened from a group gets an up-arrow back to it.
  • Group settings. A group can set the same settings a book can: domain, research mode, Background, spoiler protection, automatic X-Ray, new X-Ray categories and depth, and the three languages, through the same pickers ("For this group"). Setting a value offers to apply it to every member; members then follow the group ("Follow group X (value)" on their Book Settings rows and in every picker) until they pick their own value, which the Group Settings screen lists as "not following" with "Re-apply to all". Books added to a group that sets values are asked once; leaving or deleting a group returns its books to the global settings, and a book whose group no longer exists (a groups file restored from an older backup, say) simply follows the global settings again.
  • Collections as a source. The book picker browses KOReader collections beside history and folders; groups can be created from a collection or filled with one, and the series scan can look in a collection.
  • A closed book's chat opened beside another open book (from a group hub, for instance) gets its own dialog again instead of the open book's actions and title.
  • Crossing the next built checkpoint installs it at any spacing; a spacing above 25% used to refuse the install (for good with automatic X-Ray off).

Chat Viewer

  • Math renders as readable formulas (#105). LaTeX in a response is shown with Greek letters, real operators, superscripts and subscripts, accents, roots, and fractions as a/b, with display formulas centered. Markdown view only, and display only: saved chats, copies and exports keep the original notation, which Obsidian and similar apps render fully. Toggle in Settings > Display Settings > Rendering > Render Math Formulas (on by default).
  • New Window Size setting (Standard / Expanded) in Settings > Display Settings > Window Size for chat, artifact, translate, dictionary and quiz windows, also on each window's gear menu. Expanded leaves only a hairline around the window; compact dictionary popups are unaffected.
  • Indented continuation lines under a list item render as part of that item instead of an empty bullet.
  • A response whose markdown is cut short mid-code-fence renders instead of falling back to plain text, and emphasis characters inside math no longer scramble the rest of the answer.
  • Exports no longer fail on Kindle ("Invalid argument"): filenames built from a title are cut on a character boundary.
  • Hold Close to get back to the page. A long press on the Close button closes the chat window, any dictionary windows under it and the highlight menu in one gesture, instead of tapping through them one at a time.
  • A reply that arrives while you have scrolled back to reread lands where you were reading, not on the last question marker (from the second reply on, the marker used to win).
  • Pressing Stop or closing the window in the moment after a streamed answer has finished, while the plugin is still reading the provider's trailing rate-limit information, no longer reports the complete answer as cancelled.

Providers and Models

  • NVIDIA is a new built-in provider: free developer program, email only, no card and no identity check. Curated model list from a live catalog probe, reasoning profile, book tools on the models where forced tool use actually worked, no web search. Models retired by the host on 2026-08-26 are pruned, response parsing (including reasoning content) is fixed, and speed tiers are placed from measured latency.
  • Test provider now shows the server's own error detail when a reachability check fails, instead of a bare failure.
  • OpenCode Zen and OpenCode Go are two new providers on one account (#107): Zen is the pay-as-you-go catalog of open-weight models, Go the subscription with its own model list. Zen's built-in list grew by nine models (GLM 5, 5.1 and 5.2, MiniMax M2.5, Kimi K2.5, Qwen 3.5 Plus and 3.6 Plus, and two experimental ids), each with its own reasoning and output profile. Each has its own key entry (the same key string under opencode and opencode_go), both send the conversation header OpenCode requires, and reasoning effort is one setting for both. GPT, Claude and Gemini through OpenCode are not supported yet (they use other endpoints).
  • One conversation id per chat. The id a chat is saved under is the id the wire saw, and it rides to the hosts that use one (OpenCode's session header, OpenRouter's session id, OpenAI's prompt cache key). No other host receives it.
  • Gemini's content filter is relaxed for books by default. Google's own filter blocks answers about violent or sexual passages, and the reply used to arrive empty and unexplained. The plugin now turns the four adjustable filter categories off for its own requests. Settings > Advanced > Provider Settings > Gemini Content Filter ("Relaxed for books" by default, "Google default" restores Google's), also on the Gemini model menu.
  • When a provider cuts a response short, it says so. A finish reason outside the normal set (a safety or content filter, a recitation block, a refusal) used to surface as "Unexpected response format" when nothing came back, or as a silently shortened answer. The reason is now named: as the error when there is no text, and as a line under a partial answer, which also keeps that answer from being cached as if it were complete. Streamed replies included.
  • Groq is now a tested provider. A reader's free key (the #106 report) let the maintainer's model audit run against Groq itself: the live model list, and the full capability battery on every built-in Groq model. The gpt-oss models reason by default with low, medium or high effort, answer up to 65,536 tokens and take the book tools; the compound models take no reasoning setting and no tools, and answer up to 8,192 tokens. Everything the plugin had assumed from Groq's documentation held, so Groq loses its community marker in the provider list.

Requests that fit your plan (#106).

Some providers count the answer budget a request asks for against a per-minute token allowance, before running anything. Since v0.21.0 the plugin asks for a large budget by default, so on Groq's free plan (8,000 tokens a minute) every request was refused, including one-word dictionary lookups, and the error text blamed book size.

  • The plugin now learns your plan's per-minute allowance from the provider's own rate-limit headers (Groq, Cerebras, OpenAI) and sizes the answer budget to fit it before sending. It learns on the first real answer, streamed ones included, and from "Test provider".
  • If a request is refused all the same, a refusal that names its numbers teaches the plan's allowance: one whose answer budget was the problem is sent once more at a budget those numbers allow, and every later request in that session is sized to fit the allowance. A burst refusal (your minute's allowance is already spent) is not resent, because it refills with time.
  • One honest tip per refusal. A burst refusal ("you used your minute") says to wait; an admission refusal explains what actually happened, and when the request itself is bigger than the allowance it names the lever for the surface you are on (scope and a new chat in a book chat, folders in the library, the artifact itself in artifact chat). A small one-word lookup refused this way no longer gets the old "lower Max Text Characters" advice, which could not have helped.
  • If the prompt alone cannot fit your plan or the model's context window, a notice says so before sending, and the request is sent anyway rather than blocked locally.
  • A background X-Ray build stopped this way now reports "request too large" instead of "unusable response", and does not retry on a 60-second timer for something deterministic. A per-minute refusal that states no numbers (Anthropic, Gemini, Cerebras) or one the bucket will admit once it refills counts as a burst: the wait tip, and the build retries once after a minute.
  • A pinned answer budget cut to fit the plan tells you it was cut.
  • The self-heal also recognizes OpenRouter's context-window wording, pre-caps the next request from it, and explains the window instead of blaming book text.
  • The provider's own wait, as a number. When a refusal names how long to wait (Groq's and OpenAI's "try again in 5s", Gemini's retry delay, or the retry-after header Anthropic and OpenRouter send), the wait tip says "about N seconds" instead of "wait", and a background X-Ray build waits exactly that long before its one retry instead of a fixed minute (a wait past ten minutes stops the build instead, with the resume rows).
  • Account walls are named as such. Used-up credits, an empty balance or a spending cap (OpenAI's insufficient_quota, Anthropic's "credit balance is too low" and monthly spend cap, DeepSeek's "Insufficient Balance", OpenRouter's "insufficient credits") get a tip that points at the account instead of "wait and try again", the error stays on screen with a Try again button for after you top up, and a background X-Ray build stops with "account credits or billing" instead of retrying. OpenRouter's "can only afford N tokens" refusal (its credit check counts the whole answer budget, so a low-credit key failed a one-line question) is resent once with that answer budget when N is worth an answer.
  • Error messages now carry the provider's own error code in parentheses, such as "(insufficient_quota)" or "(rate_limit_exceeded)", which is what tells two providers' identical sentences apart.
  • Checked on a real free Groq key (2026-09-07): the plugin learned the 8,000-token allowance from Groq's headers on the first answer and sized the next request to fit. Groq has since changed its limiter: the gpt-oss models now admit the old 32,768 budget (the photographed refusal did not reproduce), while some models carry a separate output-tokens-per-minute bucket (1,000 a minute on the preview Qwen models of that account). Both of Groq's new wordings are in the plugin's corpus: one that can never fit is resent once with a budget under the output limit, a spent bucket gets the wait tip with Groq's own seconds.

Ollama

  • The plugin asks the server how big the loaded model's context window actually is before sending a prompt that will not fit, warns with the real number, and says afterwards when only part of the request reached the model (Ollama silently cuts the earliest book text to fit its window). New "Context window" row in the Ollama model menu.

API keys

  • Keys are cleaned to printable characters when read, which heals a key pasted with an invisible character or an interior line break (the Kindle case where a key copied out of a wrapped text file kept returning 401). Saving a key reports how many stray characters were removed.

Storage

Per-book plugin data left KOReader's metadata.lua (#72).

  • Chats now live in <book>.sdr/koassistant_chats.lua, and every per-book plugin setting in <book>.sdr/koassistant_book_settings.lua, next to the cache and notebook files the plugin already kept there.
  • The move is automatic: a bulk pass runs once at start-up, with catch-up passes when a book is opened or first touched, and it copies and verifies before removing anything.
  • Consequences: KOReader's "Reset this document" no longer wipes your chats and per-book settings, and KOReader's optional metadata archive no longer carries chats.
  • A book store now follows a mid-session change of KOReader's "Book metadata location" instead of leaving its file behind.

Backup and restore

  • Book groups are included in backups (and per-book settings ride along as well).
  • Restoring a backup made before the chat storage change now imports its chats instead of restoring them where nothing reads them.
  • "Quick: Fresh start" also clears the leftover chat-import backup folder once migration is complete.
  • Deleting a notebook now also clears the book's pointer to it, so the book no longer refers to a notebook that is gone.

Other

  • Console Debug is scoped to the plugin: turning it on brings back the plugin's own tracing without raising KOReader's global log level (which used to bury it under core's per-paint output). Routine tracing is no longer written to crash.log when debug is off, and plugin tracing is also emitted when KOReader's own verbose logging is on. A few per-page-turn lines that Console Debug used to write at the info level moved to the debug level too, and the marking line no longer lists entity names.
  • One long-press menu on every action button. Holding an action in the highlight menu, the dictionary popup, Quick Actions, an input dialog or the file browser menu now opens the same small menu instead of a description on some surfaces and nothing on others: the description at the top, "Add to" or "Remove from" this menu, "Other placements..." for the rest of its menus, and "Edit...", "Duplicate as custom action..." or "Reset to default". Adding or removing takes effect where you are standing, without a trip to Settings.
  • New {user_input} placeholder for custom actions. Text typed in the input dialog can be placed inside a prompt where you want it, instead of only being appended at the end. It is in the editor's placeholder list as "Typed Input"; before this the placeholder was offered but never filled in, so the braces were sent to the model as they were.
  • The update check reads version tags correctly. Two-part tags (v0.22) are no longer skipped when looking for the newest release, and pre-release tags sort the way they should: rc.11 is newer than rc.9, alpha comes before beta before rc, and a final release beats its own release candidate.
  • The Domain & Research picker opens on the book tab whenever a book is open, from the input dialog's Domain chip and from holding the Quick Settings Domain tile; it used to open on Global until the book had an override of its own.
  • Settings rows that open a picker or a manager (Categories and Depth of New X-Rays, the action and domain managers, the menu ordering managers, backups, the index tools, Test Connection, Check for Updates, About) now leave the settings menu open behind them instead of closing the whole menu.
  • Section-scoped artifacts are back on the Book Hub (only the X-Ray versions group is filtered out there, since the X-Ray browser owns it).
  • Highlight menu defaults reordered so the two conditional rows sit last: Translate, Explain, Quick Explain, Summarize, Quick Define, Dictionary, then Look up in X-Ray and Generate Image. Existing users keep their configured list.
  • Edited book metadata is honored everywhere: a title or author changed in KOReader's Book information now shows and is sent in artifact and notebook pickers, groups, merge labels, the library scan, notebook filenames, backup labels and the chat history browser. The chat history index carries it and refreshes the moment you edit it.
  • The chat history browser opens without reading each book's sidecar, which is noticeably faster on a large library.
  • The per-book Quick Answer default now resolves the book the action targets, not whichever book is open.
  • Quiz generation asks for answer options of comparable length, specificity and style.
  • Text extraction reaches the document's last page (whole-document builds used to stop at the start of it), SSE id: and retry: lines from a streaming server are ignored instead of read as data, nested list bullets are drawn as filled dots at every depth instead of hollow circles and squares, and long code lines wrap in the chat viewer instead of being cut off at the right edge.

Work in Progress

  • Cross-book lookups, the Group Hub and group settings are new and touch a lot of surfaces. Device reports welcome; the group settings for chat behavior (tools, web search, effort dials, contexts) are planned for the next version.
  • Request sizing is verified against a local stub and, for the header path, on a real free Groq key. A live Groq refusal has not been reproduced (Groq admitted the old budget on 2026-09-07), so the refusal path stands on Groq's own wording from the report.
  • AI Book Tools stays off by default while retrieval quality matures.
  • Setup Wizard v2 is still built but not switched on.

How You Can Help

  • Device reports, especially on the X-Ray first-build confirmations, cross-book lookups in a series, and the storage move.
  • Translations: review passes on Weblate.
  • Bug reports and feature requests.

Don't miss a new koassistant.koplugin release

NewReleases is sending notifications on new releases.