v1.14.0

drizzle-team/drizzle-ormv1.14.0Jul 21, 2026by lfnovo

AI Summary

v1.14.0 is a providers-and-plumbing release introducing six new connection methods, hardening outbound requests against DNS rebinding, and fixing failure modes that could break installations after redeploy.

Key Highlights

  • DNS-rebinding hardening: Outbound provider requests are now pinned to a vetted IP address.
  • New AI providers: Cohere, PayPerQ, Novita, oMLX, and expanded OpenRouter capabilities.
  • Docling formula & vision toggles: Extract mathematical formulas and describe images via vision models.
  • Configurable worker concurrency: Adjust source processing load via environment variables.

Breaking Changes

  • Outbound provider URLs are DNS-pinned: Endpoints pointing to cloud-metadata addresses are now refused.
  • `OLLAMA_BASE_URL` was never read: Users must switch to `OLLAMA_API_BASE`.
  • Docling and local Crawl4AI are now opt-in: Extraction degrades to 'auto' if runtimes are missing.

New Features

  • Anthropic-compatible credential provider for Kimi and similar endpoints.
  • Configurable worker max tasks via `OPEN_NOTEBOOK_WORKER_MAX_TASKS`.
  • New ElevenLabs models (eleven_v3, eleven_flash_v2_5, etc.) in discovery.
  • Podcast episode profiles expose a 'Max output tokens' field.

Full Release Notes

**We recommend all users upgrade.** v1.14.0 is a providers-and-plumbing release: six new ways to connect models, a DNS-rebinding hardening pass on every outbound provider call, and fixes to two failure modes that could silently break a working install after a redeploy. Validated through the full release process — backend/frontend suites, a fresh-install and an upgrade test against real Docker images, and an end-to-end pass over the running app.

## 🔒 Security hardening

- **Outbound provider requests are now pinned to a DNS-vetted IP.** Validating a URL and then handing it to the HTTP client left a rebinding window: the hostname was resolved again at connect time, so a name that passed validation could point at a cloud metadata endpoint on the actual connection. Resolution now happens once, dangerous addresses are rejected, and the request is pinned to the vetted address while `Host` and TLS SNI keep the original hostname — so certificate verification and routing are unaffected. Applied to credential saves, connection tests and model discovery (#1063)
- **Private IPs, `localhost`, `host.docker.internal`, LAN hostnames and Tailscale addresses remain fully supported** — this is a self-hosted application and local providers are a first-class use case. That guarantee is now pinned by regression tests rather than left implicit (#1193)
- Error text returned by the sources API is capped, so internal exception detail from extraction libraries no longer reaches clients (#1136)
- Resolved all open Dependabot alerts: `mcp` → 1.28.1 (3 high, transitive via content-core) and `axios` → 1.18.1 (#1191)

## ✨ New features

- **Four new AI providers**: **Cohere** (language + embedding via its native v2 API), **PayPerQ / PPQ** (multi-modality gateway — language, embedding, STT, TTS), **Novita** (OpenAI-compatible LLM gateway), and **speech-to-text on the existing Deepgram provider** (#1170)
- **oMLX as a first-class provider** — native Esperanto profile, default base URL `http://localhost:11435/v1`, connection test and model discovery, no remapping to `openai-compatible` (#1048)
- **OpenRouter now does text-to-speech and speech-to-text**, not just LLMs and embeddings. Note that its TTS model uses Microsoft neural voice names (e.g. `en-US-AvaNeural`), not OpenAI's `alloy`/`nova` set (#987)
- **`anthropic_compatible` credential provider** for endpoints that speak only the Anthropic Messages format, such as Kimi (#675)
- **Docling formula & vision enrichment toggles** in Settings → Content Processing — extract mathematical formulas as structured markup, and describe images / extract chart data with a vision model. Both opt-in and off by default; vision is significantly slower (#1131)
- **Worker concurrency is configurable** via `OPEN_NOTEBOOK_WORKER_MAX_TASKS` (default 5). Set it to 1 on single-GPU or local-LLM setups that were being overloaded by parallel source processing (#893)
- Newer ElevenLabs models in discovery — `eleven_v3`, `eleven_flash_v2_5`, `eleven_flash_v2`, and `scribe_v2` for STT (#1167)
- Podcast episode profiles expose an optional **"Max output tokens"** field in the UI, with help text explaining it caps output per generation step (outline + transcript) and defaults to the built-in values when blank (#991)

## ⚡ Performance

- **Typing in the chat composer no longer lags in long conversations.** Composer state is isolated from the message list and each row is memoized, so a keystroke no longer re-renders the whole history. Most noticeable for IME users (Japanese, Chinese, Korean), where every composition event was triggering a full re-render (#1147)

## 🐛 Notable fixes

- **A selected content-processing engine whose runtime isn't installed no longer breaks ingestion silently.** The engine choice lives in the database; the opt-in runtimes that serve it come from environment flags. A redeploy that drops `OPEN_NOTEBOOK_ENABLE_CRAWL4AI`/`_DOCLING` therefore left the setting pointing at nothing, and every extraction failed with an unhelpful "Could not extract any text content" — with the URL engine set to Crawl4AI, that broke URL ingestion entirely. Extraction now degrades to the `auto` chain and logs which engine and which flag are involved (#1194)
- **An HTTP proxy no longer kills the worker on startup.** `websockets` 15.0 began routing even `ws://` connections through `HTTP_PROXY`, so the internal SurrealDB socket was tunneled through the external proxy, rejected with a 403, and took the worker down. The internal DB hosts are now added to `no_proxy` at startup, merged with any value you set (#1160)
- Vertex credentials now configure text-to-speech correctly when used through a stored credential rather than environment variables — previously it crashed on an unexpected `project` argument (#1151)
- Auto-assign no longer re-fills optional model slots you deliberately cleared; it now only fills the two required slots, and empty optional slots show what they fall back to (#1098)
- Per-transformation model selection actually takes effect — an assigned `model_id` was persisted but ignored at execution time, so every transformation ran on the global default (#1137)
- PPQ model discovery lists all modalities, not just chat (#1180)
- Deleting a notebook now also deletes its chat sessions instead of orphaning them (#1124)
- Japanese (ja-JP) translations reviewed and improved throughout (#998)
- The quick-start and Ollama compose examples used `OLLAMA_BASE_URL`, which nothing reads — the correct variable is `OLLAMA_API_BASE`. Following them verbatim left Ollama permanently unavailable with no error explaining why (#1148)

## ⚠️ Behavior changes for self-hosters

1. **Outbound provider URLs are DNS-pinned.** Local and private endpoints are explicitly still supported. If you use an endpoint whose hostname resolves to a link-local or cloud-metadata address, it will now be refused — that is the intended protection.
2. **`OLLAMA_BASE_URL` was never read.** If you copied it from the old quick-start, switch to `OLLAMA_API_BASE` — your Ollama was not connected.
3. **Worker concurrency default is unchanged (5)** but now adjustable via `OPEN_NOTEBOOK_WORKER_MAX_TASKS`. It is read at worker launch, so restart the worker after changing it.
4. **Docling / Crawl4AI stay opt-in** (`OPEN_NOTEBOOK_ENABLE_DOCLING`, `OPEN_NOTEBOOK_ENABLE_CRAWL4AI`). If you had one selected as your engine and the flag is missing after this upgrade, extraction now falls back to `auto` and logs it, instead of failing.

## 🙏 Thanks

- **@Gautam-Diwan** — the DNS-pinning hardening on outbound provider requests (#1063), the first-class oMLX provider (#1164), and the Ollama env var correction in `.env.example` (#1064)
- **@mvanhorn** — the `anthropic_compatible` credential provider (#1043) and episode profile max output tokens in the UI (#992)
- **@kentalos** — a thorough review and rewrite of the Japanese (ja-JP) translations (#998)
- **@dyzur** — a pre-commit configuration mirroring the CI gates, so contributors catch lint/type failures before pushing (#1129)

And thank you to everyone who filed issues this cycle — several fixes here started as a report describing a setup we could not have guessed at.

Full details in the [CHANGELOG](https://github.com/lfnovo/open-notebook/blob/main/CHANGELOG.md).