DeepTutor v1.5.8 Release Notes
Release Date: 2026.08.02
A maintenance release with one target: memory that stays put instead of climbing. A v1.5.7 source deployment grew past 14 GB before V8 gave up mid-session, and the causes turned out to be independent — a frontend dev server whose heap ceiling never reached the process holding the memory, unbounded in-process caches, and a fresh HTTP client built for every turn. Drop-in — no migrations, but a source checkout now starts differently.
What's New
The dev server was never actually capped
next dev renders in a worker it spawns itself, and V8 flags in argv are not inherited by child processes — so the long-standing node --max-old-space-size=4096 …/next dev never reached the process that holds the memory. Finding no ceiling in NODE_OPTIONS, Next substituted 50% of total RAM: a 12 GB heap on a 24 GB machine, which V8 genuinely tried to fill before dying in Ineffective mark-compacts near heap limit after 63 seconds inside a single mark-compact. web/scripts/dev.mjs now passes the ceiling through NODE_OPTIONS, which the worker does inherit and Next honors — clamped to 4 GB, and sized against the cgroup limit inside a container rather than the host's RAM.
Source installs serve a production build
deeptutor start from a checkout now builds the frontend once into .next-deeptutor and serves the standalone output, reusing that build until an input actually changes (a fingerprint over the web/ tree, the version file, and the build-time public settings). Hot reload moves to deeptutor start --dev, which keeps using .next — separate directories, so neither mode invalidates the other's output while it is running. A long-running deployment no longer pays for a dev compiler's caches.
Bounded LLM clients instead of one per turn
The chat, research and question pipelines each built a fresh OpenAI-compatible client — and with it a new HTTP connection pool — on every turn. Both the agentic client and the services-layer provider now come from a small event-loop-local LRU pool of 2, keyed on binding, model, credentials and base URL, closed on shutdown and retired when settings change. Only the selected backend's SDK is imported.
Caches with a ceiling
Knowledge-task log streams now cap events and bytes per task, expire an hour after a task ends, and leave a small completion tombstone so a late subscriber still learns the task finished. The completed-task table keeps 256 entries. The LlamaIndex index cache drops from 8 entries to 2 and evicts anything idle for 10 minutes. A book runtime is released once its queue drains instead of living for the process.
Reclaiming what was already freed
After a turn, a finished book job, or a completed knowledge-base task, DeepTutor collects cycles and — on Linux — calls malloc_trim so glibc hands free heap pages back instead of holding arenas that make RSS look permanently pinned. Containers and deeptutor start also set MALLOC_ARENA_MAX=2 and a lower trim threshold, both overridable by an operator who has tuned their own.
A keep-alive race that surfaced as 500s
web/proxy.ts forwards to the backend over Node's http.globalAgent, which reaps idle sockets on a 5s timer — identical to uvicorn's default. Both ends armed the same timer on the same socket and raced to close it; when the server's FIN landed on a socket the pool was simultaneously handing to a new request, that request died with ECONNRESET and reached the UI as "Failed to load sessions". Every uvicorn launch now sets --timeout-keep-alive 300, leaving the client as the only side that retires an idle connection.
Assorted
deeptutor.agents,deeptutor.core.agentic, the provider-core package, the document extractor's parser libraries (PyMuPDF, pypdf, python-docx, openpyxl, python-pptx) and the LLM error-mapping rules all resolve on first use rather than at import time.python -m deeptutor.api.run_serverno longer starts with--reload; exportDEEPTUTOR_DEV_RELOAD=1for it. Reload runs a supervisor plus a worker and retains file-watcher state, which is development machinery.deeptutor serve --reloadis unchanged.
Upgrade Notes
Drop-in from v1.5.7: pip install -U deeptutor; Docker users pull ghcr.io/hkuds/deeptutor:latest. No schema or config changes.
- Source checkouts build before they serve. The first
deeptutor startafter upgrading runsnpm run buildand takes correspondingly longer; later launches reuse it until the source changes. Usedeeptutor start --devfor the previous hot-reload loop. The newweb/.next-deeptutor/build directory is git-ignored. python -m deeptutor.api.run_serverno longer reloads by default. ExportDEEPTUTOR_DEV_RELOAD=1to restore it.
Full Changelog: v1.5.7...v1.5.8