# KI: Claude schlägt vor, der Nutzer entscheidet Since 2026-10-24. Organisation help with Claude (Anthropic) across diora: books and magazines first; podcasts, news/blogs and projects follow (same building blocks). ## The key: the user's own, end-to-end encrypted, only on the devices Two providers, chosen in the settings (decided 2026-10-25): **Anthropic** (the official SDK) or **OpenRouter** (the same Claude model, `anthropic/claude-opus-5.5`). OpenRouter's Anthropic-compatible endpoint refuses the headers a browser call needs (`anthropic-version` …, checked by a CORS preflight), so diora talks to OpenRouter's chat completions instead: plain `fetch`, `response_format` json_schema (strict), `reasoning.effort`; no fallback on refusals, and OpenRouter sees what is sent too. The vault keeps `{provider, anthropic_key, openrouter_key}` (an old `{anthropic_key}` still reads as Anthropic); a key is checked before it is kept (Anthropic: the model's info; OpenRouter: `GET /api/v1/key`). Decided with the user: the API key is entered in the app ("KI-Assistent", the ✦ of a feature or the app menu) and stored like the books — encrypted with the book key on the device, kept by the server as a blob it can't read: - `GET/POST /accounts/vault//` (`accounts.UserVault`, name `ai`): `{ct, iv}`; `{ct: ''}` removes it. Its own store, not the library prefs (`/books/prefs/` is rewritten whole when the folder order is saved). - The devices decrypt it into memory only and call Claude **directly** from the page (browser, the apps' WebView, the desktop). The diora server sees neither the key nor what is sent; Anthropic sees what a feature needs (titles, authors, folder names …). Anthropic bills the user. - Without the book key on a device (or after a password change, which changes the book key) the key can't be read: the settings ask for it again. Not on diora Reader (e-readers). - Server-side jobs (in the background, without an app open) were left out on purpose: they would need the key on the server. The project Radar has its own server key (docs/projects.md). ## Building blocks (`static/js/ai.js`, an ES module) - The official SDK, `@anthropic-ai/sdk` 0.133.0, bundled for the browser with esbuild 0.28.2: `static/vendor/anthropic-sdk-0.133.0.mjs` (licence beside it). `dangerouslyAllowBrowser`: the key is the user's own. To update: `npm install @anthropic-ai/sdk@ esbuild` in an empty folder, `esbuild entry.mjs --bundle --format=esm --platform=browser --target=es2020 --minify` with `export { default } from '@anthropic-ai/sdk'`, and change the import in ai.js. - `DioraAI.ask({system, prompt, schema, effort})`: model `claude-opus-5-5`, structured output (`output_config.format` json_schema), effort `low` by default, streamed, `fallbacks: "default"` (beta `server-side-fallback-2026-07-01`) for declined requests; refusals and over-long answers become plain German messages. - `DioraAI.review({title, intro, items, onApply})`: the suggestions with checkboxes — nothing changes until the user ticks and presses "Übernehmen". - `DioraAI.settings()`, `withKey(fn)`, `progress()`, `showError()`, `toast()`; the sheets close with Android's back key; ⚙ in each sheet opens the settings. ## Features | area | where | what Claude gets | what it suggests | |---|---|---|---| | Bücher, Zeitschriften | ✦ in the library's head (`static/js/app/55-library-tools.js`) | per book: id, title, author, folders, series, magazine mark; the existing folders | folders to add (existing first; new ones only for ≥ 3 books), series with volume, cleaned title/author where broken, magazine mark | | Podcasts | ✦ in Abos (diora-android `web-native/static/native-podcast.js`, copied to `static/podcasts/`) | per subscription: title, author, folders, level, heard in 12 months, publishing interval, three newest episode titles | folders to add (≤ 2), level Stamm / Strom / Auf Abruf (only with a clear reason) | | Nachrichten, Blogs | ✦ in the feeds' bar (`static/js/feeds.js`; the apps' section bar presses it) | per source: title, address, kind, Ressort or folders, recent titles shown | Ressort for news, folders for blogs, news ↔ blog when clearly wrong | Applied through `_updateBookMeta` (the encrypted meta, as when editing by hand).