Skip to content

Latest commit

 

History

History
441 lines (352 loc) · 32.4 KB

File metadata and controls

441 lines (352 loc) · 32.4 KB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[Unreleased]

Added

  • VISION.md — the product's source of truth in two layers: durable identity (what Open Notebook is and is not, core principles) and current posture (the phase we're in, directional constraints, and the horizon clusters under consideration)
  • Decision records at docs/7-DEVELOPMENT/decisions/ — short, immutable ADRs/PDRs answering "why is it like this?", seeded with 4 retroactive ADRs (SurrealDB, Esperanto, Streamlit→Next.js, Surreal Commands) and 2 PDRs (single-user first, provider-agnostic core)
  • AGENTS.md files (root, open_notebook/, frontend/) with the normative rules for coding agents and humans — commands, hard rules, and gotchas not derivable from the code; CLAUDE.md files are now one-line pointers to them
  • Five new engineering docs pages under docs/7-DEVELOPMENT/: credentials, content processing, podcasts, prompts, and frontend architecture
  • Contribution guidelines for AI-assisted and agent-generated PRs in the contributing guide — the operator owns the PR, issue-first still applies, tests must have actually run
  • CI check for broken relative links in markdown (scripts/check_md_links.py + docs-links workflow on PRs touching *.md)
  • cubic.yaml — AI review settings as code: PR-contract instructions, three custom review agents (vision & principles alignment backed by VISION.md, known mechanical caveats, security & testability) and automatic ultrareviews for auth/credential/encryption/migration changes
  • Documented the flow-driven release process in .github/RELEASE_PROCESS.md, including the ready to main to stable release path, dev/stable image labels, and maintainer verification checklist (#938)
  • List view for the Notebooks page — a tile/list toggle in the header lets you switch between the visual card grid and a compact row layout (name, description, source/note counts, last updated) for easier scanning of large collections. The choice is remembered across reloads and translated across all 14 locales (#885)
  • Documented the ESPERANTO_TTS_TIMEOUT environment variable (default 300s) in the environment reference; raise it for slow or self-hosted TTS providers so long podcast segments don't fail with a timeout (#937)
  • SECURITY.md with a coordinated-disclosure policy: how to privately report a vulnerability via GitHub's private vulnerability reporting, supported versions, and response expectations (#943)
  • LaTeX math rendering (KaTeX) now also applies to source content, source insights, Ask answers, transformation output, and the note editor preview — previously only chat had it (#269)
  • Syntax highlighting for fenced code blocks in chat responses, source content, insights and Ask/Search answers — light/dark aware, with 25 common languages bundled (others render as plain text) (#783)
  • "Recently Viewed" section on the Notebooks page — a collapsible grid of the last 12 notebooks and sources you opened, newest first, hidden when there's no view history. Backed by a new last_viewed_at timestamp stamped on read and a GET /api/recently-viewed endpoint (translated across all 14 locales) (#850)
  • Per-transformation model selection — each transformation can now be assigned its own language model from the transformation editor, overriding the global transformation default for that transformation only. Runs without an explicit model keep using the system default as before (#776)
  • "Refresh content" action on web-link sources — re-fetches the URL and re-embeds the source so its content stays current, available from the source card menu once processing has completed (translated across all 14 locales) (#259)

Changed

  • Developer documentation restructured: 17 knowledge-heavy CLAUDE.md files consolidated into the 3 AGENTS.md + docs pages above; README.dev.md became a pointer after its unique content moved into development-setup.md (make-workflow matrix), .github/RELEASE_PROCESS.md (Docker publishing) and the change playbooks (add-a-language); the maintainer guide now carries the curated label taxonomy (state funnel, area: labels, consolidation rules)
  • Fixed stale developer docs while migrating: real migration path/format (open_notebook/database/migrations/N.surrealql + AsyncMigrationManager registration), provider count (17), locale list (7), and 9 README links that pointed at documentation pages that never existed
  • The API's listen interface in the Docker images is now configurable via a new API_HOST environment variable instead of a hardcoded --host 0.0.0.0. The default is unchanged (0.0.0.0); set API_HOST=:: to serve IPv6/dual-stack environments (#985)
  • docker-compose.yml now sources the SurrealDB credentials from SURREAL_USER / SURREAL_PASSWORD (applied to both the database server and the app), defaulting to root:root so the zero-config quick start is unchanged. Set them in a .env file to use your own credentials before exposing the instance; .env.example and the compose file note this (#946)

Fixed

  • API startup no longer crashes when SurrealDB isn't ready yet (e.g. docker-compose race on host reboot: Temporary failure in name resolution). The lifespan now polls a lightweight readiness probe with bounded exponential backoff (~50s budget, 5s per-probe timeout) before running migrations; migration errors themselves still fail fast (#708)
  • Markdown typography styles (prose classes) are active again: the Tailwind v4 migration left the old tailwind.config.ts (which loaded @tailwindcss/typography) silently ignored, so rendered markdown lost its typographic styling. The plugin and class-based dark mode are now configured in globals.css, and markdown rendering is centralized in a shared MarkdownRenderer component (#783)
  • Podcast generation no longer truncates on dense, long-form content (LengthFinishReasonError / OUTPUT_PARSING_FAILURE): episode profiles now support an optional max_tokens that is passed through to podcast_creator's outline/transcript generation, overriding its defaults — settable via the episode profile API (UI follow-up in #991) (#639)
  • API no longer freezes for all requests while a chat waits on the LLM. Both the notebook chat (execute_chat) and source chat handlers ran LangGraph's synchronous invoke() directly on the event loop; they now run it via asyncio.to_thread() (matching the existing get_state calls), so other requests stay responsive — and the source-chat SSE can flush its early events instead of stalling until the model finishes (#704)
  • Windows native install guide no longer points users at a start-open-notebook.bat that doesn't exist in the repo; the Quick Start now documents starting the four services manually with uv run, plus an optional sample launcher you can save yourself (#846)
  • OpenRouter (and other providers') "Discover models" dialog no longer cuts off the submit button: the dialog now uses a fixed header/footer with a scrollable body (grid-rows-[auto_1fr_auto]) instead of scrolling the whole content, so the "Add" button stays visible regardless of how many models are listed (#816)
  • Chat references using the short [insight:<id>] form (emitted by some models) are now rendered as clickable citations like [source_insight:<id>] and [note:<id>] already were; insight is treated as an alias for source_insight, so clicking it opens the insight (#490)
  • CRUD endpoints now return 404 (not 500) for a non-existent resource. ObjectModel.get() raises NotFoundError rather than returning a falsy value, so the broad except Exception in each handler was masking it as a server error. Added an explicit NotFoundError → 404 arm to the notebook (update / delete / delete-preview / add-source / remove-source), note (get / update / delete / list / create), model (delete), credential (update / delete) and embed handlers (#862)
  • Token counting no longer raises ValueError: disallowed special token '<|endoftext|>' when source/context content contains special-token sequences; token_count() now encodes with disallowed_special=() so such substrings are treated as ordinary text (#667)
  • Single-container image no longer hangs at "API not ready yet" on a brand-new instance. supervisord.single.conf ran the API and worker with uv run (without --no-sync), so at startup uv tried to sync dev dependencies it couldn't resolve against the --no-dev build. Both processes now use uv run --no-sync, matching the multi-container supervisord.conf (#609)
  • Note editor now expands to fill the dialog instead of being capped at 500px; removed the max-h-[500px] constraint that overrode the flex-1 parent and cramped editing on tall windows (#932)

Security

  • Resolved dependency audit findings: added npm overrides for vulnerable transitive frontend packages (ws, brace-expansion, ajv, @eslint/plugin-kit, postcss) — npm audit now reports 0 vulnerabilities — refreshed uv.lock (langsmith, pydantic-settings, pip), and hardened external window.open(..., '_blank') calls with noopener,noreferrer (#962)

[1.10.0] - 2026-06-17

Security

  • Bumped Starlette to 1.2.1 and FastAPI to 0.136.3 to address CVE-2026-48710 ("BadHost"), a denial-of-service in Starlette's host header handling (#859)

Added

  • LaTeX math rendering in chat — inline ($...$) and display ($$...$$) expressions are now rendered with KaTeX (#606)
  • NEXT_PUBLIC_API_TIMEOUT_MS environment variable to configure the frontend API request timeout (default 600000 = 10 minutes; set 0 to disable). Lets slow/long-running chat models finish without editing source (#880)
  • Bulk chat-context actions in a notebook, via a "Context" menu in the Sources and Notes column headers — translated across all 14 locales (#223):
    • Sources: "Include all (insights only)" (sources without insights are left out rather than forced to full), "Include all (full content)", and "Exclude all from context"
    • Notes: "Include all in context" / "Exclude all from context"
  • Turkish (tr-TR) localization — the UI is now fully translated into Turkish (#871)

Changed

  • Failed source cards now show a prominent "Retry processing" button directly on the card instead of only inside the 3-dot dropdown; clicking it no longer also opens the source (the click was missing stopPropagation) (#726)
  • Docker base image updated to Debian trixie and Node.js 22.x (#914)

Fixed

  • Podcast generation now uses the notebook's real content. Notebook.get_context() was missing, so generation ran against empty context; it now assembles source and note content as expected (#864)
  • PUT profile handlers now use model_dump(exclude_unset=True), so partial updates no longer overwrite unspecified fields with defaults (#860)
  • OpenRouter embedding models are now correctly recognized via their embedding modality (#842)
  • Search and Ask results now use page-level scrolling instead of being confined to a cramped, height-capped (60vh) bottom container, so the full result set is readable (#882)
  • POST /sources/{id}/retry no longer returns 400 "Source is not associated with any notebooks" for every source; it now queries the reference graph edge by its in/out columns instead of a non-existent source column (#861)
  • POST /sources/{id}/retry no longer returns a 500 ("too many values to unpack") after successfully queuing the retry job; the command ID was being double-prefixed (command:command:…) before being saved to the source. Retrying a failed source now succeeds and updates the source's command reference
  • GET /sources/{id} for a missing or deleted source now returns 404 instead of 500; the handler caught NotFoundError in its generic except and mapped it to a server error
  • Sources that fail to ingest (e.g. an unreachable or invalid URL) are now marked failed instead of silently saved as completed with the extraction error as their body. This means the "Retry processing" button (#726) actually appears for the most common failure mode; previously the job returned a failure payload but the command still completed, so the source never reached a retryable state (#726)
  • Text search no longer returns a 500 when SurrealDB's search::highlight hits a "position overflow" on large or multi-byte document chunks; it now falls back to vector search and returns results (#648)
  • POST /api/search now rejects a non-positive limit with a 422 instead of passing LIMIT -1/LIMIT 0 to SurrealDB (which caused a 500 or a silently empty result set) (#863)
  • Ollama num_ctx credential override is now persisted. The credential table gained a flexible config object (migration 15) and provider-specific tuning options are stored there instead of being dropped by the SCHEMAFULL table; future per-credential options can be added without a schema migration (#875)
  • Worker no longer crashes on queued jobs from older versions; legacy embedding command aliases (embed_single_item, embed_chunk, vectorize_source) are registered and delegate to the current commands so stale queues drain cleanly (#695, #876)

Performance

  • Notebook source list no longer re-renders every SourceCard on unrelated state changes (layout toggles, context selection), and completed sources no longer each open a status-polling query. Both scaled with the number of sources and caused UI lag on large notebooks (#503)

[1.9.0] - 2026-06-02

Added

  • New audio providers, surfacing the capabilities added in Esperanto 2.21–2.22:
    • Mistral Voxtral speech-to-text (voxtral-*-latest) and text-to-speech (voxtral-mini-tts), reusing the existing Mistral credential (#827)
    • Deepgram text-to-speech (Aura voice catalog) as a new provider (DEEPGRAM_API_KEY) (#827)
    • xAI text-to-speech (#827)
    • Google speech-to-text & text-to-speech, Vertex text-to-speech, and ElevenLabs speech-to-text (Scribe), completing the audio provider matrix (#828)
  • Optional per-credential num_ctx (context window) override for Ollama models, configurable in Settings → API Keys and translated across all 13 locales (#825)
  • OPEN_NOTEBOOK_EMBEDDING_BATCH_SIZE environment variable to override the embedding batch size; default remains 50. Helps with CPU-only local embedding and stricter OpenAI-compatible endpoints (#735)
  • CORS_ORIGINS environment variable to configure the API's allowed origins (comma-separated). Default remains * for backward compatibility; the API now logs a startup warning prompting users to set it for production deployments. Exception responses honor the configured origins when explicitly set (#585, #597, #730)
  • OPEN_NOTEBOOK_MIN_CHUNK_SIZE environment variable (default: 5 tokens) to filter out degenerate tiny chunks before embedding. Set to 0 to disable.

Changed

  • Bumped Esperanto 2.20.0 → 2.22.0. Beyond the new audio providers above, this inherits several upstream fixes and behavior changes (see below).

Inherited from Esperanto 2.21–2.22

  • Fixed: OpenRouter LLM and embedding requests now send a proper JSON body (previously sent a malformed form-encoded payload).
  • Fixed: OpenAI-compatible endpoints (e.g. llama.cpp) that return null embeddings now raise a clear, descriptive error instead of an opaque TypeError.
  • Fixed: Streaming tool calls now return proper ToolCall objects across Anthropic, Google, Vertex, and Ollama.
  • Fixed: base_url trailing slashes are normalized across providers, preventing double-slash URLs (and 301 redirects) for Ollama and other self-hosted endpoints.
  • Fixed: Ollama "thinking" models (e.g. Qwen) now merge their reasoning content correctly.
  • Fixed: Model discovery honors a custom base_url (LiteLLM/vLLM/OpenAI-compatible proxies).
  • Behavior change: the Ollama default context window (num_ctx) is now 8192 (was 128000) to avoid out-of-memory errors on consumer GPUs. Raise it per-credential via the new num_ctx field if your hardware allows.
  • Behavior change: the Google embedding default model is now gemini-embedding-001 (the previous default, text-embedding-004, was removed from Google's API). If you used Google embeddings with the old default, re-create the model and re-embed your content (embedding dimensions changed).
  • Fixed: Google TTS default model updated to a currently-working preview model.

Fixed

  • URL source embedding no longer crashes with TypeError: float() argument must be a string or a real number, not 'NoneType' when header-based splitters emit single-character fragments from complex HTML pages (e.g. Wikipedia, Project Gutenberg). Such chunks are now filtered before being sent to the embedding provider (#764)
  • Language toggle now uses t('common.german') instead of a hardcoded "Deutsch" label, matching the pattern used by every other language entry (follow-up to #794)
  • Speech-to-text model connection tests now transcribe a short bundled speech clip instead of silence, so a passing test returns real text instead of a blank transcription (#838)

[1.8.5] - 2026-04-14

Changed

  • Embedding chunking is now token-based instead of character-based, improving chunk sizing consistency for CJK and mixed-language content (#542, #749)
  • OPEN_NOTEBOOK_CHUNK_SIZE and OPEN_NOTEBOOK_CHUNK_OVERLAP semantics changed from characters to tokens; default reduced from 1200 characters to 400 tokens to stay safely below the 512-token ceiling of BERT-family embedders (e.g. mxbai-embed-large) after accounting for tokenizer mismatch and splitter overshoot. Existing stored embeddings are unaffected; only new ingestions use the new chunking.

Fixed

  • Credentials endpoint no longer crashes (500) when encryption key doesn't match stored credentials (#740)
  • Broken credentials are now shown with a decryption warning and can still be deleted
  • DELETE endpoint for broken credentials supports model migration (migrate_to parameter)

[1.8.4] - 2026-04-09

Security

  • Fix Remote Code Execution (RCE) via Jinja2 Server-Side Template Injection in transformations (CVSS 9.2 Critical)
  • Fix arbitrary file write via path traversal in file upload (CVSS 7.0 High)
  • Fix arbitrary file read via Local File Inclusion in source creation (CVSS 8.2 High)

Dependencies

  • Bump ai-prompter to >=0.4.0 (uses Jinja2 SandboxedEnvironment to prevent SSTI)

[1.8.3] - 2026-04-07

Security

  • Fix SurrealDB injection via unsanitized order_by query parameter in GET /api/notebooks (CVSS 8.7 High)
  • Add allowlist validation for sorting parameters in notebooks endpoint
  • Replace f-string query interpolation with parameterized $variable binding in source chat and migration queries
  • Add defensive validation in get_all() base method to prevent injection via order_by parameter

[1.8.2] - 2026-04-06

Added

  • DashScope (Qwen) and MiniMax provider support via Esperanto v2.20.0 (#725)
  • Source list auto-refresh after adding a new source via URL, file upload, or text (#721)

Fixed

  • Source asset persistence — failed sources now persist their asset (URL/file path), making them identifiable and retryable (#722)
  • Source title preservation — user-set custom titles are no longer overwritten after background processing (#722)
  • Credential cascade delete — deleting a credential now removes linked models instead of returning a 409 error (#722)
  • Podcast directory names — uses UUID for episode directories, fixing filesystem errors with special characters (#666)
  • Tiktoken offline handling — API no longer crashes in air-gapped environments (#622)
  • SurrealDB healthcheck — removed incompatible healthcheck from Docker Compose (#656)
  • Esperanto embedding fixes — base_url/api_key config issues across multiple embedding providers (#664, #665)

Docs

  • Deprecated single-container Docker image in favor of Docker Compose (#723)

Dependencies

  • Bump esperanto to >=2.20.0

[1.8.1] - 2026-03-10

Added

  • i18n support for Bengali (bn-IN) (#643)
  • Podcast language support via podcast-creator 0.12.0 (#645)
  • Upgrade default Azure API version for model testing and fetching (#638)

Fixed

  • Tiktoken network errors in offline/air-gapped Docker deployments — pre-downloads encoding at build time (#264, #622)
  • SurrealDB getting stuck (#656)

Dependencies

  • Bump esperanto to 2.19.5 (#657)
  • Bump langgraph from 1.0.6 to 1.0.10rc1 (#658)
  • Bump authlib from 1.6.6 to 1.6.7 (#649)
  • Bump lxml-html-clean from 0.4.3 to 0.4.4 (#646)
  • Bump rollup from 4.55.1 to 4.59.0 (#635)
  • Bump minimatch in frontend (#634)
  • Bump tar from 7.5.9 to 7.5.11 (#650, #659)

[1.7.4] - 2026-02-18

Fixed

  • Embedding large documents (3MB+) fails with 413 Payload Too Large (#594)
  • generate_embeddings() now batches texts in groups of 50 with per-batch retry, preventing provider payload limits from being exceeded
  • 413 errors now classified with user-friendly message in error classifier
  • Misleading "Created 0 embedded chunks" log in process_source_command — embedding is fire-and-forget, so the count was always 0; now logs "embedding submitted" instead

[1.7.3] - 2026-02-17

Added

  • Retry button for failed podcast episodes in the UI (#211, #218)
  • Error details displayed on failed podcast episodes (#185, #355)
  • POST /podcasts/episodes/{id}/retry API endpoint for re-submitting failed episodes
  • error_message field in podcast episode API responses

Fixed

  • Podcast generation failures now correctly marked as "failed" instead of "completed" (#300, #335)
  • Disabled automatic retries for podcast generation to prevent duplicate episode records (#302)

Dependencies

  • Bump podcast-creator to >= 0.11.2
  • Bump esperanto to >= 2.19.4

[1.7.2] - 2026-02-16

Added

  • Error classification utility that maps LLM provider errors to user-friendly messages (#506)
  • Global exception handlers in FastAPI for all custom exception types with proper HTTP status codes
  • getApiErrorMessage() frontend helper that falls back to backend messages when no i18n mapping exists

Fixed

  • LLM errors (invalid API key, wrong model, rate limits) now show descriptive messages instead of "An unexpected error occurred" (#590)
  • SSE streaming error events in source chat and ask hooks were swallowed by inner JSON parse catch blocks
  • Transformation execution errors were caught and re-wrapped as generic 500s instead of using proper status codes
  • Fail fast when source content extraction returns empty instead of retrying (#589)
  • Chat input and message overflow with long unbroken strings (#588)
  • Word-wrap overflow in source cards, note editor, inline edit, note titles, and dialog content (#588)
  • Translation proxy shadowing name keys (#588)
  • OpenAI-compatible provider name handling via Esperanto update (#583)

Changed

  • ValueError replaced with ConfigurationError in model provisioning for proper error classification
  • ConfigurationError added to command retry stop_on lists to avoid retrying permanent config failures

Dependencies

  • Bump esperanto to 2.19.3 (#583)
  • Bump podcast-creator to 0.9.1

[1.7.1] - 2026-02-14

Added

  • French (fr-FR) language support (#581)
  • CI test workflow and improved i18n validation (#580)
  • Expose embed command_id in note API responses (#545)

Fixed

  • ElevenLabs TTS credential passthrough via Esperanto update (#578)
  • Handle empty/whitespace source content without retry loop (#576)
  • Increase transformation max_tokens and update Esperanto dep (#568)
  • Turn the embedding field into optional (#557)

Docs

  • Fix docker container names in local setup guides (#577)

Dependencies

  • Bump langchain-core from 1.2.7 to 1.2.11 (#564)
  • Bump cryptography from 46.0.3 to 46.0.5 (#563)

[1.7.0] - 2026-02-10

Added

  • Credential-Based Provider Management (#477)

    • New Settings → API Keys page for managing AI provider credentials via the UI
    • Support for 14 providers: OpenAI, Anthropic, Google, Groq, Mistral, DeepSeek, xAI, OpenRouter, Voyage AI, ElevenLabs, Ollama, Azure OpenAI, OpenAI-Compatible, and Vertex AI
    • Secure storage of API keys in SurrealDB with field-level encryption (Fernet AES-128-CBC + HMAC-SHA256)
    • One-click connection testing, model discovery, and model registration per credential
    • Migration tool to import existing environment variable keys into the credential system
    • Azure OpenAI support with service-specific endpoints (LLM, Embedding, STT, TTS)
    • OpenAI-Compatible support with per-service URL configurations
    • Vertex AI support with project, location, and credentials path
    • Environment variable API keys deprecated in favor of Settings UI
  • Security Enhancements

    • Docker secrets support via _FILE suffix pattern (e.g., OPEN_NOTEBOOK_PASSWORD_FILE)
    • Default encryption key derived from "0p3n-N0t3b0ok" for easy setup (change in production!)
    • Default password "open-notebook-change-me" for out-of-box experience (change in production!)
    • URL validation for SSRF protection - blocks private IPs and localhost (except for Ollama which runs locally)
    • Security warnings logged when using default credentials
  • HTML clipboard detection for text sources (#426)

    • When pasting content, automatically detects HTML format (e.g., from Word, web pages)
    • Shows info message when HTML is detected, informing user it will be converted to Markdown
    • Preserves formatting that would be lost with plain text paste
    • Bump content-core to 0.11.0 for HTML to Markdown conversion support
  • Improved Getting Started Experience

    • Simplified docker-compose.yml in repository root (single official file)
    • Added examples/ folder with ready-made configurations:
      • docker-compose-ollama.yml - Local AI with Ollama
      • docker-compose-speaches.yml - Local TTS/STT with Speaches
      • docker-compose-full-local.yml - 100% local setup (Ollama + Speaches)
    • Inline quick start in README (no need to navigate to docs)
    • Cross-references between docker-compose examples and documentation
    • .env.example template with all configuration options

Fixed

  • Azure form race condition: all configuration now saved in single atomic request
  • Migration API "error error" display: added proper MigrationResult model with message field
  • Connection tester for Ollama providers: improved error handling and URL validation
  • SqliteSaver async compatibility issues in chat system (#509, #525, #538)
  • Re-embedding failures with empty content (#513, #515)
  • Deletion cascade for notes and sources (#77)
  • YouTube content availability issues (#494)
  • Large document embedding errors (#489)

Security

  • API keys are encrypted at rest using Fernet symmetric encryption
  • Keys are never returned to the frontend, only configuration status
  • SSRF protection prevents internal network access via URL validation

Docs

  • Complete documentation update for credential-based system across 25 files
  • All quick-start, installation, and configuration guides now use Settings UI workflow
  • Environment variable API key instructions moved to deprecated/legacy sections
  • Fixed broken links in installation docs
  • Added comprehensive examples/ folder with documented docker-compose configurations
  • Updated local-tts.md and local-stt.md with links to ready-made examples

Internationalization

  • Added Russian (ru-RU) language support (#524)
  • Added Italian (it-IT) language support (#508)

[1.6.2] - 2026-01-24

Fixed

  • Connection error with llama.cpp and OpenAI-compatible providers (#465)
    • Bump Esperanto to 2.17.2 which fixes LangChain connection errors caused by garbage collection

[1.6.1] - 2026-01-22

Fixed

  • "Failed to send message" error with unhelpful logs when chat model is not configured (#358)
    • Added detailed error logging with model selection context and full traceback
    • Improved error messages to guide users to Settings → Models
    • Added warnings when default models are not configured

Docs

  • Ollama troubleshooting: Added "Model Name Configuration" section emphasizing exact model names from ollama list
  • Added troubleshooting entry for "Failed to send message" error with step-by-step solutions
  • Updated AI Chat Issues documentation with model configuration guidance

[1.6.0] - 2026-01-21

Added

  • Content-type aware text chunking with automatic HTML, Markdown, and plain text detection (#350, #142)
  • Unified embedding generation with mean pooling for large content that exceeds model context limits
  • Dedicated embedding commands: embed_note, embed_insight, embed_source
  • New utility modules: chunking.py and embedding.py in open_notebook/utils/
  • Japanese (ja-JP) language support (#450)

Changed

  • Embedding is now fire-and-forget: domain models submit embedding commands asynchronously after save
  • rebuild_embeddings_command now delegates to individual embed_* commands instead of inline processing
  • Chunk size reduced to 1500 characters for better compatibility with Ollama embedding models
  • Bump Esperanto to 2.16 for increased Ollama context window support

Removed

  • Legacy embedding commands: embed_single_item_command, embed_chunk_command, vectorize_source_command
  • needs_embedding() and get_embedding_content() methods from domain models
  • split_text() function from text_utils (replaced by chunk_text() in chunking module)

Fixed

  • Embedding failures when content exceeds model context limits (#350, #142)
  • Empty note titles when saving from chat (clean thinking tags from prompt graph output)
  • Orphaned embedding/insight records when deleting sources (cascade delete)
  • Search results crash with null parent_id (defensive frontend check)
  • Database migration 10 cleans up existing orphaned records

[1.5.2] - 2026-01-15

Performance

  • Improved source listing speed by 20-30x (#436, closes #351)
    • Added database indexes on source field for source_insight and source_embedding tables
    • Use SurrealDB FETCH clause for command status instead of N async calls

[1.5.1] - 2026-01-15

Fixed

  • Podcast dialog infinite loop error caused by excessive translation Proxy accesses in loops
  • Podcast dialog UI freezing when typing episode name or additional instructions
  • Removed incorrect translation keys for user-defined episode profiles (user content should not be translated)

[1.5.0] - 2026-01-15

Added

  • Internationalization (i18n) support with Chinese (Simplified and Traditional) translations (#371, closes #344, #349, #360)
  • Frontend test infrastructure with Vitest (#371)
  • Language toggle component for switching UI language (#371)
  • Date localization using date-fns locales (#371)
  • Error message translation system (#371)

Fixed

  • Accessibility improvements: added missing id, name, and autoComplete attributes to form inputs (#371)
  • Added DialogDescription to dialogs for Radix UI accessibility compliance (#371)
  • Fixed "Collapsible is changing from uncontrolled to controlled" warning in SettingsForm (#371)
  • Fixed lint command for Next.js 16 compatibility (eslint instead of next lint)

Changed

  • Dockerfile optimizations: better layer caching, --no-install-recommends for smaller images (#371)
  • Dockerfile.single refactored into 3 separate build stages for better caching (#371)

[1.4.0] - 2026-01-14

Added

  • CTA button to empty state notebook list for better onboarding (#408)
  • Offline deployment support for Docker containers (#414)

Fixed

  • Large file uploads (>10MB) by upgrading to Next.js 16 (#423)
  • Orphaned uploaded files when sources are removed (#421)
  • Broken documentation links to ai-providers.md (#419)
  • ZIP support indication removed from UI (#418)
  • Duplicate Claude Code workflow runs on PRs (#417)
  • Claude Code review workflow now runs on PRs from forks (#416)

Changed

  • Upgraded Next.js from 15.4.10 to 16.1.1 (#423)
  • Upgraded React from 19.1.0 to 19.2.3 (#423)
  • Renamed middleware.ts to proxy.ts for Next.js 16 compatibility (#423)

Dependencies

  • next: 15.4.10 → 16.1.1
  • react: 19.1.0 → 19.2.3
  • react-dom: 19.1.0 → 19.2.3

[1.2.4] - 2025-12-14

Added

  • Infinite scroll for notebook sources - no more 50 source limit (#325)
  • Markdown table rendering in chat responses, search results, and insights (#325)

Fixed

  • Timeout errors with Ollama and local LLMs - increased to 10 minutes (#325)
  • "Unable to Connect to API Server" on Docker startup - frontend now waits for API health check (#325, #315)
  • SSL issues with langchain (#274)
  • Query key consistency for source mutations to properly refresh infinite scroll (#325)
  • Docker compose start-all flow (#323)

Changed

  • Timeout configuration now uses granular httpx.Timeout (short connect, long read) (#325)

Dependencies

  • Updated next.js to 15.4.10
  • Updated httpx to >=0.27.0 for SSL fix