Changelog / release
0.12.8 — The desktop app makes pictures
Released 2026-08-10 · full changelog · GitHub releases
A new Images tab renders locally, Chat reads the images you attach, and a wide band of engine correctness fixes lands underneath — including the packaging bug that would have shipped the Images tab unable to render anything in a downloaded copy.
- The desktop app generates images. The Images tab renders through the same one-model-per-process server the chat uses: pick an image model (
z-image-turboorflux2-klein-4b), load it through the usual readiness gate, prompt, and refine. Renders land in a filmstrip you can step back through, and selecting an older one restores the prompt that produced it (#1705). Two launch-blockers were caught before shipping: the bundled sidecar was missingmflux, so a downloaded copy could never actually generate (#1768), and the disk-space gate mis-counted already-cached component-layout weights as an impending download and refused to start (#1773). - Chat reads the images you attach. With a vision model loaded, attach an image to a message and ask about it; models that cannot read images show the attach button disabled with an explanation instead of failing later (#1723).
- The Qwen tool-call parser handles awkward arguments correctly. A series of fixes to
qwen3_coder_xmladdresses legacy raw string arguments whose own content contains XML-like closing tags — where the parser cannot tell an argument’s text from the wrapper around it. Some variants produced wrong arguments, others leaked wrapper framing into the answer or dropped the text after a call (#1730).AutoToolParser’s balanced-JSON scan was fixed alongside (#1726), and a replayed terminal chunk undertool_choice: autono longer duplicates content into the answer (#1711). tool_choice="none"is honored everywhere. A tool-trained model could emit a call — with a name and arguments that were never even declared — on the exact turn a client had turned tools off; the call is now dropped and the prose kept, across every parser and both stream modes (#1761). Literal<tool_call>or<think>tags in ordinary prose survive instead of being eaten (#1766, #1779), mid-conversationsystemmessages reach Harmony / gpt-oss models instead of being silently dropped (#1769), and a truncated chain-of-thought is marked as incomplete rather than shipped as the answer (#1770).- The first follow-up message no longer re-reads the opening context. The opening turn never saved a reusable cache boundary, so the second message paid to re-prefill everything; reuse already worked from the third message on. Measured on
qwen3.6-27b-4bitwith a ~9.9K-token document: the follow-up prefills 34 tokens instead of 9,941 — 1.45 s instead of 32.4 s (#1732). LFM2.5-2.6B gains bounded prefix reuse too: its alias saidis_hybrid: falsewhile the runtime found hybrid layers, so every turn re-prefilled the whole context (#1764). - The server survives sustained load and rude clients. The scheduler reclaims paged full-KV and free-block memory instead of wedging on a
D-METAL-CAP503 (#1646), a streaming client disconnecting mid-generation no longer leaks a running slot until the server wedges (#1782), andGET /healthreturns 200 for image-gen and video-gen serves instead of 500 for the life of the serve (#1783). - Reasoning-plus-tools turns get a real token budget. The desktop’s floor for those turns was set to exactly the default budget, so the
max()meant to lift it never lifted anyone; it is now 16,384 while Max Tokens sits at its default. A short budget does not fail loudly — it returns a cut-off answer that reads as a model that “could not do it” (#1722). - Desktop paper cuts. “Browse all models” opens the catalogue instead of closing the wizard (#1662); a stale last-served alias is validated before restore, so a removed model no longer fails the launch (#1729); returning to Chat after loading an Images model switches the server back instead of leaving the load button inert (#1739); the chat tab reports one throughput number instead of three, because prefill is no longer charged to tokens/second (#1728); web-page approvals gain “Always allow” with private and local addresses still blocked (#1695); and Claude Code gets an agent profile (#1720).
- The release process itself got trustworthy. App and engine are cut in one event instead of two that could drift (#1649); a release gate that had not run for eleven releases was found dead and repaired (#1671); the Codex review step fails closed on backend, auth, timeout or execution failure instead of passing silently (#1700); and four AX-only GUI golden flows run on every desktop PR — driving the app through the accessibility API with no screen recording, so they work unattended in CI (#1721, #1731, #1708).