We recommend all users upgrade. v1.15.0 brings the new "Quiet Green" visual identity, three new provider options (SiliconFlow, Z.ai, MiniMax text-to-speech), and the latest Esperanto, content-core and podcast-creator releases. Behind them is a long list of fixes to failures that used to be silent: podcasts that never appeared, sources stuck as "Processing...", workers that stalled, answers cut short. Validated through the full release process: backend and frontend suites, a fresh-install and an upgrade-from-1.14.0 test against the published images, and an end-to-end pass over the running app (API and UI), including podcasts on OpenAI, Anthropic, Gemini and DeepSeek.
🔒 Security
- Credential encryption now uses PBKDF2-HMAC-SHA256 (600k iterations) with versioned ciphertext. New keys are written in the new
pbkdf2v1:format, and existing keys keep decrypting. A one-shotPOST /api/credentials/migrate-encryptionupgrades stored keys (idempotent, fail-closed per record). See the downgrade note below (#1317, #1360) - Dependency security update:
next16.3.8 (critical RCE advisory innext/og; Open Notebook doesn't usenext/og),axios,postcss,brace-expansion, and Pythonanyio,pyjwt,tornado,urllib3,virtualenv. Security floors are now pinned so a future lock can't resolve back to vulnerable versions (#1404, #1414) - The
pillowoverride is gone: podcast-creator no longer pulls in moviepy, and content-core now requirespillow >= 12.3.0itself (#1440)
✨ New features
- "Quiet Green" visual identity. A new design foundation co-designed with the community in Discussion #1202 (a token system for color, type, radius and shadow; Bricolage Grotesque, Instrument Sans and Spline Sans Mono), applied screen by screen: app shell, notebook workspace, sources library, dialogs, models, settings, podcasts and search. Works in light and dark themes (#1202)
- New providers: SiliconFlow (hosted DeepSeek, Qwen, GLM and Kimi; mainland-China accounts set the credential's Base URL to
https://api.siliconflow.cn/v1) and Z.ai (the GLM family), both with connection test and model discovery (#1409, #1437) - MiniMax text-to-speech. MiniMax voices can now be used in podcast speaker profiles (
speech-2.8-hd,speech-2.8-turbo), and MiniMax moves toMiniMax-M3with a 1M-token context. Region-specific keys can setMINIMAX_BASE_URL/ the credential Base URL (#1438) - OpenDocument uploads:
.odt,.ods(one table per sheet) and.odp(one block per slide), plus.htmfiles (#1439) - YouTube when YouTube blocks your server: set
CCORE_YOUTUBE_PROXY(a residential proxy) orCCORE_YOUTUBE_COOKIES_FILE(a browsercookies.txt) on the worker to get transcripts through.CCORE_AUDIO_SEGMENT_MINUTEScontrols how long audio is split before transcription (#1439) - Podcasts in your language again: episode profiles'
languagesetting is honored for outlines and transcripts (#1334) - Podcasts sound more natural, with a short (~400 ms) pause between speaker turns, and audio combining no longer cuts off the end of a turn (#1446)
- Podcast failures now explain themselves: a wrong speaker name, a voice the TTS model doesn't support, or a truncated response each get a specific hint (#1334)
- The search page explains what text and vector search each cover; a "New Source" button sits on the empty sources state; the "API Keys" settings page is now "Models" (#1295, #1165, #1313)
🐛 Notable fixes
- Podcasts work on a fresh install. The seeded speaker profiles ship without a voice model, and any unconfigured profile used to fail every podcast with
validation errors for SpeakerConfig, even one generated with a fully configured profile (#1450) - Podcasts work with models that don't support JSON schema output (DeepSeek, older vLLM / llama.cpp servers). Outlines and transcripts use schema-validated output and fall back to plain JSON when an endpoint rejects it. Prompts no longer show the model a placeholder skeleton it could copy back, which used to abort episodes mid-generation (#1446, #1334)
- Failed sources fail once, with a clear reason. An unreachable or missing page, a malformed URL, a corrupted file or a YouTube video without a transcript now fails on the first attempt with a specific message, instead of being retried up to 15 times (#1433)
- The worker no longer stalls when a source or transformation is deleted before or while it's processed. Database failures are no longer misreported as "not found", so they stay retryable (#1363, #1364)
- Context-length errors aren't retried for ~25 minutes in background jobs anymore; they fail immediately with an explanation (#1275)
- Ask answers are no longer truncated. Its three stages were capped at 2000 output tokens; they now share the 8192 budget chat uses (#1221)
- An empty model reply is an error, not an answer, in chat, source chat, Ask and transformations. A failed chat turn no longer leaves the question in the history, so retrying doesn't duplicate it (#1392)
- Source chat: the streamed reply no longer repeats earlier answers, no longer drops or corrupts tokens across network chunks, and the context badge survives a page refresh (#1393, #1289)
- Transformations no longer run on sources with no text and save an invented insight (#1394)
- A partially failed embedding job no longer leaves a source looking embedded while search sees only part of it (#1390)
- Vector search always returns results by descending similarity; text hits on insights open their parent source (#1306, #1339, #1345)
- The YouTube transcript language preference in Settings is honored again (#1287)
- Remote Crawl4AI servers that require a bearer token work again (
CRAWL4AI_API_TOKEN) (#1269) - Clearing a notebook or transformation description now persists (#1396)
- Passwords with non-ASCII characters work for API authentication (#1290)
- Note editor follows the dark theme and shows list markers; long voice-model names no longer overflow profile cards; sidebar footer actions are aligned (#1294, #1300, #1259, #1288)
- The Anthropic connection test no longer reports retired model ids as a permissions error (#1303)
ESPERANTO_SSL_*settings now apply to connection tests and model discovery (#1214)
⚠️ Behavior changes for self-hosters
- Model calls now time out after 180 seconds by default. Esperanto 2.28 enforces
ESPERANTO_LLM_TIMEOUTon every provider. Before, most providers used their SDK default and Ollama waited indefinitely. If you run slow local models, raise it on the API and worker, e.g.ESPERANTO_LLM_TIMEOUT=420. Keep it under 600: the web UI gives up on a request after 10 minutes. - Back up your database before migrating credential encryption. Versions before v1.15.0 can't read the new
pbkdf2v1:format. Upgrading is safe (old keys keep working), but after you run the encryption migration, rolling back needs that backup. - Podcast outline and transcript default to 8192 output tokens (were 3000 / 5000). If your outline or transcript model has a lower output limit (some older or local models stop at 4096), set the episode profile's Max output tokens below it.
- Sources that used to "complete" with empty content now fail. content-core 2.2 raises on extraction errors, so a page that couldn't be fetched shows up as a failed source with its reason instead of an empty one.
- API: a database failure while loading a single record returns 500, not 404, so clients can tell an outage from a missing record.
- API passwords must be sent as UTF-8. Clients that sent non-ASCII passwords as Latin-1 bytes need to switch.
🙏 Thanks
This release is mostly community work. Thank you:
- @alefbt: podcast language instruction and the copyable-skeleton fix, with failure hints that actually match the failure (#1334)
- @GF-2025: diagnosed and fixed the worker stalling on deleted sources (#1364)
- @SomSamantray: versioned PBKDF2 credential encryption (#1360)
- @justadityaraj: UTF-8 passwords, search results that open the right record, and insights after long generations (#1344, #1345, #1346)
- @Alphaxiaoteng: dark-theme markdown editor, list markers, Anthropic connection test and vector search ordering (#1294, #1300, #1303, #1306)
- @hydraxman: insight search hits and Anthropic-compatible podcast models (#1339, #1350)
- @pacocartones: source chat stream parsing and surfaced retry warnings (#1289, #1342)
- @AugustoSandim: search coverage docs and the "Models" settings rename (#1295, #1313)
- @bitsandbots: auth docs,
allowedDevOriginssupport and quieter KaTeX warnings (#1189, #1190, #1208) - @mvanhorn: OpenAI-compatible base URL guidance and the Write Note editor (#1251, #1286)
- @gblue1223: batched embedding inserts over one connection (#1293)
- @Creepyrishi: no more retrying context-length errors (#1275)
- @dalexsys:
ESPERANTO_SSL_*for connection tests and discovery (#1214) - @dyzur, @zivkidd1: Ask's loading state no longer gets stuck (#1146, #1235)
- @thomaspockrandt: "New Source" on the empty state (#1165)
- @fyshark: source dialog action overlap (#1195)
- @Msparihar: long voice-model badges (#1259)
- @Sure-Will: sidebar footer alignment (#1288)
- @Dessalines39394: the README star-history chart (#1262)
- @jeffersongoncalves: SHA-pinned GitHub Actions and Dependabot (#1271)
- @Ercaner1988: the Docker-to-native Windows migration guide (#1374)
And thanks to everyone who reported issues, shared logs and reproduced bugs. Many of the fixes above started with a precise report.