Skip to content

v0.18.0

Choose a tag to compare

@github-actions github-actions released this 14 Jul 03:29
v0.18.0
5df969a

Follow-ups from 0.17.0

Three of 0.17.0's ADRs named a remaining follow-up; this release closes them.

Presets get their admin surface

0.17.0 shipped configuration presets as admin-gated AJAX endpoints; the Configurations backend module now puts them in front of the admin. A pending-presets panel — rendered only while a declared preset has no record — shows each preset's name, identifier, purpose, and its preflight result: the model the criteria currently match, or the requirement no configured model satisfies. One click imports a satisfiable preset through the existing endpoint. Imported records whose declaration changed since import carry a non-blocking "Preset changed" badge (checksum comparison; hand-created records that share a declared identifier are not flagged). The checksum-driven update flow remains future work (ADR-056, #357).

Translator usage rows get the right user

The specialized translator path bypasses the middleware pipeline, so the beUserUid a caller set on TranslationOptions never reached its usage tracking — translator rows always fell back to the ambient backend user. TranslationService now re-attaches the resolved uid to the options array it hands to TranslatorInterface implementations, and the DeepL and LLM translators forward it to trackUsage(). The key is pipeline metadata: implementations must not send it to the remote API, and the interface documentation says so. Speech and image services keep ambient attribution — their option shapes carry no budget fields (ADR-052, #358).

One exception class for validation errors

Nine remaining classes threw PHP's global InvalidArgumentException on input validation; they now throw nr_llm's Exception\InvalidArgumentException, so these errors are catchable through NrLlmExceptionInterface like the rest of the public surface. Backward compatible — the nr_llm class extends the SPL one, existing catches keep matching. TaskInputResolver keeps the global import: its only use is a catch around third-party code that can raise the plain SPL exception, which a subclass-narrowed catch would miss (ADR-053, #359).

Also in this release

The POST-and-reload boilerplate that backend list modules had each copied now lives in one shared ModuleAction.js helper, used by the configurations and tool-state modules; the other backend list modules still use the copied version. The 0.17.0 changelog was backfilled with the two Ollama entries (#341/#342) that had shipped without one (#356).

Pull requests

#356, #357, #358, #359, #360 — ADRs in Documentation/Adr/.

Full changelog: v0.17.0...v0.18.0