Changelog
Generated from the LlamaNexus-WebUI repo's own
CHANGELOG.md- see source for the definitive version. Runnode scripts/sync-changelogs.mjsto refresh this page.
[0.1.19] - 2026-07-28
Changed
- License enforcement is disabled - no license key configured no longer blocks chat sends. Reported as an informational "running unrestricted" status instead of a block, with zero license API calls made when no key is set. The heartbeat loop is otherwise unchanged and still runs whenever a key is configured
[0.1.18] - 2026-07-22
Changed
- Hugging Face search/listing now goes through the LlamaNexus proxy's
/api/hf/searchand/api/hf/repo-filesendpoints instead of calling huggingface.co directly -HF_TOKENno longer needs to be set on this backend at all (removed fromdocker-compose.yml); configuring it once on the proxy covers gated/private repo access everywhere
[0.1.17] - 2026-07-22
Changed
- The license key field in Settings is now masked (
type="password") instead of shown in plain text
Added
LLAMANEXUS_LICENSE_KEYenvironment variable sets the license key without touching Settings at all (e.g. indocker-compose.yml) - takes precedence over the Settings value, reflected via a newlicenseKeyFromEnvflag that disables the Settings field accordingly, and never gets baked back into the persisted settings fileLLAMANEXUS_PORT/LLAMANEXUS_BIND_HOSTenvironment variables override the listen port/host the same way, useful for dodging a port conflict on the host.gitignorenow also excludes a repo-root.env(docker-compose.yml's own expected location for these), previously onlybackend/.envwas covered
[0.1.16] - 2026-07-22
Added
- Privacy Policy / Terms of Service / Usage Policy links on the Account settings tab, shown whether logged in or out
[0.1.15] - 2026-07-22
Fixed
- Closed a gap in the previous release's license-key requirement: if a key was configured but
llamanexus.accountApiBaseUrl/accountApiBaseUrlwas left empty, the app silently ran unrestricted instead of blocking, since that check fell outside the new block-on-missing-key logic.accountApiBaseUrlnow defaults to the real hosted service instead of empty, and an explicitly-blanked value now blocks immediately with a clear message instead of falling into the 7-day connectivity grace period, which could never actually resolve a local misconfiguration
[0.1.14] - 2026-07-21
Changed
- A license key is now required to send chat messages at all, closing the loophole where leaving it blank ran the app unrestricted forever regardless of trial status. Backend startup (before any heartbeat runs) now blocks chat sends immediately if no key is configured, with a status-line reminder to add one - zero calls to the license API are made until you do. Once a key is set, the existing heartbeat/grace-period/block behavior takes over unchanged
[0.1.13] - 2026-07-21
Changed
- The account API now tracks WebUI and VS Code installs as independent limits instead of a shared "client" pool (Basic/Pro plans effectively double in device capacity as a result: the same per-kind numbers now apply to each separately), and adds a new unlimited-everything Enterprise plan. This app's license heartbeat now reports its install kind as
webuiinstead of the old genericclientso it's counted correctly on the account server - no local settings or behavior change, purely a server-side reporting fix
[0.1.12] - 2026-07-21
Changed
- License enforcement now has real teeth: the account API's Free tier was renamed to a time-limited Trial, and a confirmed payment problem (trial expired, payment past due, or an invalid license key) now blocks sending new chat messages -
handleUserMessagerefuses immediately with anassistant_errorbefore any side effects, while everything else (settings, past sessions) stays fully usable. Being over your plan's device count (install_limit_reached) stays a soft warning in Settings only, unchanged - that's a capacity issue, not a payment one. Opt-in behavior and the 7-day connectivity grace period are both unchanged - this only changes what happens on a confirmed denial
[0.1.11] - 2026-07-20
Added
- Add optional license registration: a new
licenseKeySettings field (Connection group) registers this install against your LlamaNexus account's plan, via a background heartbeat once at backend startup and every 6h after (backend/src/license/). Saving a new/changed key also triggers an immediate check so Settings shows a result right away instead of waiting for the next tick. Opt-in only - leaving it blank makes no license API calls at all. A confirmed denial shows a status line under the field immediately but never blocks chatting; a plain connectivity failure stays silent for up to 7 days before showing anything, so a temporary outage doesn't produce a false warning
[0.1.10] - 2026-07-19
Fixed
- The context-usage bar above the composer always showed the fallback
contextSizesetting (4096 by default) instead of the connected model's real context size, once the proxy reported no model asloaded(e.g. an idle/discovery-mode proxy) - it fell back to whichever model happened to be first in/models, an arbitrary, often-wrong context size. Now resolves the context size by matching the session's actual configured model (its own override, else the global default) first, the same precedence used to build the real outbound request, withloadedonly as a secondary fallback - The "Thinking" section disappeared from a reply whenever the model made a tool call right after reasoning, while a plain-text reply's thinking content was kept correctly - the tool-call code path never attached the accumulated reasoning to the persisted message, unlike the plain-answer path. Fixed by threading it through consistently on both paths
[0.1.9] - 2026-07-19
Added
- Trash-based chat deletion: deleting a chat now moves it to a Trash section in the sidebar (between the session list and the server section, collapsed by default) instead of erasing it immediately. Trashed chats can be restored, or permanently deleted individually or all at once via an "Empty trash" icon on the Trash section's title row. A new Chat Appearance setting, Auto-accept "Move to trash", lets you skip the confirmation dialog for that first step - permanently deleting an item or emptying the trash always still confirms
Fixed
PUT /api/settingssilently dropped any setting not listed in the backend's hand-maintained key whitelist - caught while adding the auto-accept-trash setting, whose checkbox appeared to save in the UI but never actually persisted. Added the missing key- The Trash section and the server-list section right below it each carried their own separator border, rendering as a doubled line between them - the Trash section no longer draws its own
- Checkboxes throughout Settings and the Controls sidebar used the browser's native white-box/blue-checkmark rendering, out of place against the app's dark palette - restyled with a themed background and a checkmark colored with the same accent used for the active session/selected server elsewhere
[0.1.8] - 2026-07-19
Added
- Per-session tool overrides: each chat can now independently enable/disable file tools, the bash tool, the planning tool, and agent delegation, defaulting to the global Tool Calling settings when left alone. Lives in a new Tools section inside the sidebar (renamed Controls, see below), collapsible independently of the existing Sampling section (the sampling-parameter list) so opening one never dumps the other open too. Each row shows two checkboxes: the effective per-session value on the left (click to override; toggling it back to match the global value clears the override again), and a read-only, greyed-out mirror of the current global setting on the right, so the global state stays visible at a glance without opening Settings
Changed
- The "Parameters" sidebar is now labeled Controls, to fit its new second section (Tools) alongside the existing sampling parameters
Fixed
- The Controls sidebar could show stale tool-override/sampling-parameter values right after switching sessions or on a full page reload, until you switched sessions again - its local draft only re-synced from the store when the active session id changed, missing the async server reply that lands a moment after joining a session. Now also re-syncs whenever that underlying data changes
[0.1.7] - 2026-07-19
Added
- A real "who's logged in" affordance: the sidebar footer's plain Settings button is now a user menu - a round avatar (initials from your username, or your email if you haven't set one) plus your name, opening a small menu with Settings and Log out. Logged out, it shows a generic avatar and a Sign in entry that opens a centered login dialog (
LoginModal) instead of requiring a trip through Settings first. The login form itself (LoginForm) is shared between this new dialog and the existing Settings → Account tab, so there's one place owning the actual login logic
Fixed
- Hugging Face model downloads got stuck on "Starting…" forever and never progressed, even though search still worked -
routes/huggingface.ts's/pullrelay listened onreq.on('close', ...)to abort if the client disconnected, but in modern Node that event fires as soon as the (small) POST body finishes being read, independent of the response - aborting the relay to the LlamaNexus proxy almost immediately on every request, with the resulting error silently swallowed. Listens onres.on('close', ...)instead, which only fires on a genuine client disconnect. Verified against a real proxy: progress now streams through correctly, and a real mid-download client disconnect still aborts cleanly - The login form's submit button rendered small and left-aligned under the full-width email/password fields above it, since it sat in a plain
<form>with no width set, unlike the flex/stretch layout other dialogs' buttons get from.confirmation-buttons. Now spans the same width as the fields above it
[0.1.6] - 2026-07-18
Added
- A new Account settings tab: log in with a LlamaNexus-Docs account (the same one used on the docs site) directly from Settings. The backend proxies the login to LlamaNexus-Docs server-side and persists the resulting token in
backend/data/account.json- never sent to the browser, the same discipline already applied toHF_TOKEN. Verified end-to-end that the token never appears in any browser-visible response (GET /api/settings,GET /api/account). NewaccountApiBaseUrlsetting (Connection group) points at your LlamaNexus-Docs deployment. Nothing is gated behind being logged in yet - this only adds the capability, ahead of a coming subscription/license system
[0.1.5] - 2026-07-18
Added
- Add
build-docker.sh <tag>to build and tag the Docker image asmakershop/llamanexus-webui:<tag>(--pushalso pushes it;IMAGE_NAMEenv var overrides the repository name)
Changed
docker-compose.ymlnow runs a pre-built image by name/tag (makershop/llamanexus-webui:${TAG:-latest}) instead of building it itself (build: .) - build one first withbuild-docker.sh, thenTAG=<tag> docker compose up -d. Verified end-to-end:build-docker.shproduces a correctly-tagged image, and compose starts a container from it (not a fresh build) that boots and serves correctly
[0.1.4] - 2026-07-18
Added
- The active chat now persists across a page reload instead of dropping back to "no session selected" - the last-selected session is remembered (
localStorage) and re-joined on load, as long as it still exists - The active chat gets the same left-edge accent "sidemark" the selected server row already had, instead of just a background-color highlight
Fixed
- The sidebar's Settings button used the Unicode ⚙ character, which rendered as a thin, barely-visible dot in the sidebar's serif font - replaced with a real solid gear/cog SVG icon (ring, 8 teeth, a punched-out center hole), and its label is centered again like before
[0.1.3] - 2026-07-18
Added
- Add
Dockerfile+docker-compose.yml(docker compose up -d --build) - a multi-stage build so only backend's production dependencies (not TypeScript/Vite/React/esbuild) end up in the runtime image.docker-entrypoint.shseedsbindHost: 0.0.0.0into the persisted settings on first boot only, since the app's own default (127.0.0.1) would otherwise be unreachable from outside the container with no way to fix it via the Settings UI (you could never reach that UI to begin with). Compose defaults tonetwork_mode: hostso LAN server auto-discovery (UDP broadcast) works, with a commented-outports:mapping as the alternative if you don't need it. Verified end-to-end (build, first-boot seeding, port reachability, settings persistence across a restart, SELinux-safe bind mounts via:z)
[0.1.2] - 2026-07-18
Fixed
- Settings' model list context size no longer says "tokens" - just the numbers (
4,096 (32,768)) - The rotating "Thinking/Chewing..." word's character-by-character reveal was silently broken: every character mounted at once and the whole word faded in together over 0.5s (a leftover
visibleclass had no matching CSS rule), instead of a real staggered typewriter effect. Characters now only mount once their turn in the reveal comes up, so the stagger is genuinely visible
Changed
- Per-character reveal is a bit slower (90ms/char, was 60ms) and once a word is fully typed it now pulses gently until the next rotation, instead of just sitting static
- Word changes now crossfade instead of cutting instantly or leaving a gap: the outgoing word fades out on its own overlay while the next word starts revealing immediately underneath, rather than waiting for the old one to fully disappear first
[0.1.1] - 2026-07-18
Added
- The sidebar is now user-resizable (drag its right edge) with a 200-480px range, and remembers both its width and collapsed/expanded state across reloads (
localStorage) - Ported the VS Code extension's rotating "Thinking / Chewing / Pondering..." word animation (same word list, character-by-character reveal, rotates every 5s) - shown in place of the role title before the first token arrives, then continues below the reply for as long as the turn is still in flight, covering gaps like a pause before a tool call
- Assistant replies (streaming and completed) show the actual model name in the role title instead of a literal "Assistant" placeholder
- User messages: "You" now aligns with the bubble's own left edge and the timestamp with its right edge (previously both were clustered together at the right, disconnected from the bubble's actual width); the copy button moved to its own row below the bubble, aligned to its right edge
- Set a default system prompt (visible/editable in Settings → Model & Generation)
- Set default temperature (0.8), max tokens (4096), and context size (4096)
- Add the
discoveryPortsetting (Connection group) - the LAN discovery UDP port was previously hardcoded, unlike the VS Code extension's ownllamanexus.discoveryPort - Picking a model from the composer's model picker now also updates Settings' "Model" field (renamed from "Default model", mirroring the VS Code extension's own
/modelpicker writing straight to its global setting); removed the "Use default" entry from the picker (picking always sets a real value now); added a "Search Hugging Face for models..." entry with a search icon at the bottom of the picker, opening the same Hugging Face search/download modal used from Settings - Settings' model list context text reformatted to match the chat view's context-usage bar (
4,096 tokens (32,768)) instead of a differently-worded4096 / 32768 trainedsuffix - Add a model-removal button (red ✕) to Settings' model list - permanently deletes the model from the LlamaNexus proxy (file(s) + its
router.preset.inientry); requires LlamaNexus 0.1.21+
Fixed
- Pressing Stop while a reply was streaming left the Send/Stop button stuck on "Stop" and the thinking animation running forever - the backend silently dropped the abort instead of settling the turn. It now saves whatever text had streamed so far (deliberately skipping tool-call synthesis - a call still being constructed when interrupted must not run) so the frontend actually hears back and resets
[0.1.0] - 2026-07-18
Added
- Sessions: create, rename, delete, and switch between chat sessions; each persists its full history, response stats, and reasoning/thinking text as a JSON file server-side
- Streaming chat over WebSocket, with markdown-ish rendering, fenced code blocks, and response stats (prompt/response/total tokens, elapsed time, tokens/sec)
- Tool calling:
read_file,write_file,patch_file,list_files,run_bash, all confined to a configurableworkspaceRoot, each gated behind a Settings toggle and an in-app confirmation dialog before touching disk update_plantool with a collapsible Plan panel above the composer, and a per-session Plan/Edit mode toggle that blocks disk/bash tools outright while in Plan Moderun_agenttool to delegate a self-contained sub-task to a separately-configured agent server, with its own bounded tool-calling loop going through the same confirmation flow as the main model- LAN server auto-discovery (UDP heartbeat) surfaced as a clickable server list in the sidebar
- Forced per-chat server selection: the composer stays disabled with a prompt until a server is explicitly picked for that session - applies uniformly to every session, old and new, matching the VS Code extension's own never-auto-select behavior.
Session.baseUrlOverrideis the field backing this - The model that most recently generated a reply is tracked server-side (
Settings.lastUsedModel) and persisted across backend restarts, then used to pre-select the model for every newly created session - RPC worker management (single/RPC mode toggle, add/remove workers, live roster) for the configured proxy, shown inline in the sidebar's server list; only the row matching the configured proxy gets these admin controls
- Hugging Face model search and download, with multi-shard quant grouping, a "✓ Downloaded" badge, and cancelable in-progress downloads
- An "Eject" button on the currently-loaded model in the model picker to unload it from the server and free its memory
- A collapsible per-session model-tuning "Parameters" sidebar (Temperature, Top K, Top P, Min P, Frequency/Presence Penalty, Repeat Penalty, Repeat Last N, Mirostat + Tau/Eta, Seed, Max Tokens, Stop Sequences)
- Slash commands (
/model,/ctx-size,/worker,/compact) with a live-filtered popup menu; the first match is highlighted while typing, arrow keys move the highlight, and Enter completes the highlighted suggestion into the composer instead of sending - The model list and slash-command popup close on Escape or a click outside the menu
- Automatic context compaction once usage crosses a configurable threshold, plus a manual
/compactcommand - A full granular Settings panel (Connection, Model & Generation, Tool Calling, Chat Appearance), backed by
GET/PUT /api/settings - In-app confirmation dialogs (deleting a chat, ejecting a model, disruptive proxy-restarting actions, tool-call writes/patches/bash) instead of native browser
confirm()popups - Toast-style system notes for background events (mode switches, plan revisions, auto-compaction)
Fixed
- Chat deletion used a native
window.confirm()popup instead of the app's own in-app dialog - now consistent with every other confirmation in the app