VAF v0.1.0a21
Pre-releaseAdded
-
The README says plainly what VAF sends and where it goes. A new
"What VAF sends, and where" section: VAF collects no usage data and reports
nothing to Veyllo, there is no analytics SDK and no crash reporter, and the
only outbound request VAF makes on its own is the startup version check
against GitHub's public releases API - which carries no data about you and
whichupdate_check_on_start: falseturns off. The section is equally plain
about the other direction: if you point VAF at a cloud provider, your prompts
go to that provider. "No telemetry" means Veyllo receives nothing; it does not
mean a cloud-backed agent works without talking to the cloud. The README badge
row now also shows the release, last commit, tool and test counts, the number
of supported LLM providers, and the supported platforms. -
The license now states, in one place, what a fork owes its users. VAF
carries a short legal notice under Section 7(b) of the AGPL, in English and
German, naming its origin and the obligations that come with it: pass it on
under the same license, make the corresponding source available, and if you run
a modified version as a network service, offer that service's users your
complete source. It also names the commercial license as the way out of those
obligations. A fork must keep the notice in its source. It does not have to
be displayed anywhere, and it restricts nothing else - renaming, rebranding and
commercial operation stay permitted, exactly as the AGPL allows. The notice is
static text: nothing about it is transmitted, and it involves no telemetry of
any kind. -
Tools can write their own log lines:
self.log(...). Every tool - including
one written by a third party against the publicBaseTool- can now report what
it is doing without reaching into VAF's internals. Lines land intools_*.log
with the tool name and session filled in, follow the sameVAF_LOG_DIRand
Debug Logssettings as everything else, and are cleaned up by the same garbage
collector. It never raises, so a logging mistake cannot fail a tool call. -
Sessions can be created, renamed and deleted inside the terminal app.
The sessions panel (Ctrl+S) gainednfor a fresh session,rto rename
the highlighted one anddto delete it after a confirmation - deleting
the session you are in is refused until you switch away./session new
and/session rename <name>do the same from the prompt. The panel now
shows the same list the web sidebar shows: messenger chats and internal
thinking runs stay in their dashboards instead of flooding the list. -
A session keeps ONE name everywhere, including across a web rename.
Renaming is now a single engine operation that changes the session file
and nothing else - before, renaming from a list could silently drag the
renamed session's saved state into the running one. The terminal app
adopts the on-disk name before saving on exit, so renaming a chat in the
web while the terminal had it open no longer loses the new name when the
terminal closes; the background worker had silently ignored web renames
altogether and now honors them. -
Switching sessions in the terminal app now shows the conversation.
Loading another session swapped the agent's memory but left the previous
conversation on screen, and a resumed session started with an empty
transcript as if nothing had ever been said. The transcript now follows: a
switch repaints the loaded conversation (the newest forty messages, with an
honest note when older ones were trimmed -/exportwrites the full
record), and starting VAF with an existing session shows its conversation
under the start banner. Replayed messages carry the time they were actually
sent. -
Automations and the tool catalog live in the terminal app's settings.
The Automations submenu shows what the classic menu showed - name, schedule,
next run, enabled state - and selecting an automation switches it on or off;
the storage folder opens from its own row. "Show All Tools" now opens the
tool catalog instead of pointing at a restart. -
The local model can be switched inside the terminal app, without losing
the conversation. "Select Active Model" now lists the models on disk with
the active one marked, and picking one swaps the running agent live: the
llama server is restarted with the chosen weights (it verifies which model
it serves instead of blindly reusing whatever runs), the model-specific
behavior follows the new weights, and the chat you were in stays. The swap
waits until the new model has loaded and says so; while a reply is being
generated it refuses instead of pulling the model out from under it. With a
cloud provider selected, picking a file stores the choice for the next time
the local provider serves - as the classic menu did. Only the model download
still points atvaf settings. -
The context limit, custom numbers, the microphone and About live in the
terminal app now. Four more settings rows stop pointing atvaf settings:
the context limit offers the classic presets plus a free value and says
honestly that it applies at the next start; the sub-agent timeout and the
auto-open tab cap take any number in their classic ranges; the microphone
submenu lists your real input devices and switches the live microphone at
once; and About shows version, licence and links without leaving the app. -
/export <file>writes the conversation from inside the terminal app -
markdown, or JSON when the filename ends in.json. The sessions panel now
shows each session's id and a line of its summary, andsession current
prints the full id - the one thingvaf run --session <id>needs and the
panel can only truncate.session listopens the panel instead of failing as
an unknown id.
Changed
- Files VAF writes and reads back now say which format they are in. Three
stores kept no format identity of their own, so a reader had to guess from the
keys it happened to find. The filesystem index cache carries a schema tag and a
cache without the current tag is rebuilt instead of being read as if it were
current - previously any JSON file at that path with a matchingoskey was
accepted, including one written by an older build or another tool. Handoff
bundles are written with a format tag, and bundles stored before the tag keep
loading, so an open handover is not lost across an update. The audit timeline's
hash chain starts from a versioned seed; timeline files written earlier start
from the old seed and still verify as intact. One visible effect: after the
update the filesystem index is rebuilt once on first use. - The tool-use log now covers every lane, not only chat.
tool_use_*.log
records which session and which user scope were behind a tool call - the first
place to look when isolation looks wrong. It was written from the chat loop
only, so workflow steps, librarian sub-tools, training samples and tools added
by an embedded application never appeared in it. The shared dispatcher writes
it now, so all of them do. Two details worth knowing: a call that a permission
check refused is logged too (a blocked attempt is exactly what this file is
opened for), and the argument preview is sanitized the same way the live event
stream already was, so a large field such as a file's contents is summarised by
length and digest instead of pasted in whole. The coder's own tool loop does not
use the shared dispatcher and is still absent. - A pip-installed VAF no longer writes logs into its own install directory.
The log directory search included the folder above the package, which in a
checkout is the repository and in a pip install is site-packages. Installed
copies now fall through to the normal application data directory; a checkout is
unaffected. SetVAF_LOG_DIRto choose explicitly. - Tool-loading diagnostics no longer print underneath the terminal app. The
per-turn tool hot-reload, the custom-tool reload and a failed provider switch
wrote their warnings straight to the raw terminal - under the full-screen app
that corrupted the display mid-conversation. These messages now travel the
same event lane as the rest of VAF's status output: the terminal app shows
them as notes, the classic terminal shows the usual styled event line instead
of a bare[WARN] ..., and the web log receives them too. vaf run --webno longer starts the background service behind your back.
The README has always described this command as the dashboard WITHOUT the tray,
and the lane hosts the dashboard itself - but if the background service was not
running, the command quietly launched it as a detached process that outlived
your session. Now the dashboard lives and dies with your session, as promised.
If you relied onvaf run --webto bootstrap the persistent service, start it
the intended way:vaf tray. A service that is already running keeps serving
unchanged.
Fixed
-
The sub-agent windows are dark in dark mode. The librarian's file browser
came up with bright, near-white panels: its window body, the file area behind
the listing and the toolbar above it were painted with fixed colour values,
and fixed values do not follow the theme. All sub-agent windows shared those
values, so the coder, research, document and browser views were bright in the
same places. They are now defined once and follow the theme. Light mode is
unchanged. -
Asking about files in one folder no longer answers about another one. The
librarian answers simple folder questions from a cached index in about a
second. That index decided which folder to report from the file type in your
question, not from the folder you named - so "how many PDFs are in Downloads"
came back with the count from Documents, fluently and fast enough to look
authoritative. Measured on one machine: 33 PDFs in Downloads, answer said 9,
which is the Documents figure. The folder you name now decides the answer; a
question with no folder gets the counts for every folder instead of a guess;
and where the index has no figures at all it stays quiet and lets a real
search run rather than reporting a zero nobody counted. -
Clearing the chat while an answer is still arriving now discards that
answer. The reply kept streaming into the freshly emptied conversation,
so a paragraph appeared with no question above it - belonging to a history
that was deleted a moment later anyway. The terminal app drops it and says
so. -
The model list no longer offers the vision helper file as a model. When
local image understanding is set up, VAF downloads a second file next to the
model - the "projector" that lets the model see pictures. It ends in.gguf
like a model, so every model picker (terminal app, classic settings, web UI)
listed it as a choice; picking it left the local server unable to start with
a crypticunsupported model architecture: 'clip'. Those files are filtered
out everywhere now, and a configuration that already points at one falls
back to a fitting model with a clear message instead of failing to start. -
Switching the local model keeps your context size and GPU setting. The
server was restarted with the defaults instead of your configured values, so
a large context window silently shrank whenever the model changed - while
the setting still showed the old number. -
Setting a plan in the terminal app works on the first try. Tools run
on the terminal app's worker thread, and that thread never learned which
session it serves - so working-memory writes (plan, notes, tasks) landed
in a global store while the plan check read the session's own, empty one.
The agent then got "set a plan first" bounces despite having just set one,
retried with reworded plans, and finally got through only because the
check gives up after three blocks. Every worker thread now knows its
session, so the plan lands where the check looks - first try. -
An edit-only coding run no longer reports failure. The coding agent
counted only files it CREATED, so a task like "add a section to the
README" ended with "Task Failed - No files were created" over a
successful, even committed edit. When nothing was created, the verdict
now asks git what changed since the run began; edits count as the
outcome, and only a run that truly changed nothing keeps the honest
failure message. -
The coder works in the folder you started VAF in. Open a terminal in
your project (an IDE terminal counts), runvaf run, ask for a code
change - the coding agent now works on THAT project. Before, the separate
terminal it runs in started in your home directory instead of your
project, so the project-detection never matched and the work landed in a
freshVAF_Projectsfolder. The main agent hands its working directory
to every spawned sub-agent and workflow now; explicit paths in the task
still win, and "create a new project" still gets a fresh folder. -
Running project tests in the sandbox works on a fresh container. The
sandbox image ships without pytest while pytest is the default test
command, so every container recreation broke "run the tests" with "No
module named pytest" until someone installed it by hand. The runner now
installs pytest on demand (once per container) and reports honestly when
it cannot. -
Old chats without an owner no longer show up in every user's list.
Sessions created before per-user ownership existed carried no owner mark,
and the session list showed such sessions to every signed-in user - their
titles were visible to people they never belonged to (opening them was
always refused). On startup VAF now marks these legacy chats as the
machine owner's, which is the only person they can belong to, and they
disappear from everyone else's list. -
The terminal app starts the Docker services, and a sleeping memory
database is named instead of impersonating an empty memory. Quitting the
desktop tray stops the service stack (database, sandbox, speech) - so a
terminal-only session afterwards ran against a stopped memory database,
and asking the agent what it remembered got "I have no stored information"
over a database full of it.vaf runnow brings the stack up in the
background exactly like the tray does (the whole start/stop logic lives in
one place now instead of only inside the tray), and when the database
really is unreachable, the memory search says so - the agent will tell you
the memory stack is down rather than declare itself amnesic. Without
Docker, everything keeps working as before, minus the services. -
Typing anything now interrupts the agent's speech in the terminal app.
The classic terminal always treated any input as "stop talking, I have
something to say" - spoken output is asynchronous and routinely outlives the
reply that produced it. The full-screen app only silenced speech when a new
turn actually started, so a slash command, a typo, or a message queued behind
a running turn left the agent talking over you. Every submitted input now
stops running speech before it is even parsed, silently; the explicithalt
still says "speech stopped". -
The settings no longer advertise a wake word. Both terminal settings
menus carried "Wake Word" labels pointing at a feature that was removed from
VAF months ago (the always-on listener was dropped in February together with
its dependency). The dead row and the labels are gone; if a wake word
returns, it returns as a real feature, not as a menu entry that leads
nowhere. -
Closing the "what's new" window no longer wipes parts of your profile. Dismissing
the update announcement sent a single value to the server, but the profile endpoint
treated everything the message did not mention as "set this to empty" - so your main
messenger, city, country, timezone and date and time format were silently cleared, and
the change was recorded as if you had edited it yourself. It happened on every release.
Emptying a field on purpose still works: the settings forms send it as an explicit
"make this empty" so it cannot be confused with a field that was simply not part
of the request. -
The profile history says who changed something, and admits when a value was
removed. Entries recorded only what was touched, and always said "updated" even when
a field had been emptied. Both made the earlier bug look like a manual edit. -
Security logs are kept for two weeks instead of two days. They sit in the same
folder as ordinary logs and follow the same naming, so the routine cleanup deleted them
after 48 hours. Nobody noticed, because a missing log looks exactly like a quiet period.
They now have their own retention (security_log_retention_days, default 14). -
Voice input works in the terminal app. Pressing
l(orlisten) opens the
recording overlay with a live level meter showing what the microphone actually
hears, and the transcribed sentence is sent as your message - the same flow the
classic terminal always had, and the conversation shows your words above the
answer. If you would rather check the transcription first, turn on "Voice:
review before send" (Settings, Voice): the sentence then lands in the input
box for you to read and fix, and enter sends it. Escape cancels the recording
itself, not just the window. The speech resources are prepared at startup
while the terminal is still plain (Piper voice download, microphone check with
an honest "pyaudio is not installed" where that is the reason, language
detection warmup), so the first use does not stall mid-chat. -
Voice capture works on machines using the Docker speech stack - which is the
default. Recording answered "no speech detected" within half a second, in the
terminal app and the classic lane alike: with the default speech engine the
microphone was simply never set up, because the engine choice was misread as
"no local capture needed" - it only decides where the audio is transcribed.
The microphone is now prepared when recording starts, and the recording goes to
the transcription lane you chose: your cloud STT provider if configured,
otherwise the local Whisper container - the same path Telegram and WhatsApp
voice messages take. It is never quietly rerouted to Google's free web API, and
a dead speech stack is named as what it is instead of "no speech detected". -
The classic recording line no longer prints formatting tags. The level
meter wrote styling markup to the raw terminal, so the classic lane showed
literally "[bold red]● SPEAKING[/bold red]" while recording - since the day it
was written. It now paints plain text. -
Browsing themes no longer changes your startup theme. Pressing
t(or
theme <name>) now switches the look for the current session only, exactly as
the classic terminal always did - the Settings > Theme row is what saves a
choice. Until now every press wrote the config immediately, so looking through
the catalog once left the LAST theme in the list as your new default: matrix,
which looks like a plain green terminal - and the next start seemed to have
lost the VAF theme entirely. The switch note now says it changed this session,
and where to save. -
Workflow variable filling is deterministic, and its log tells the truth.
When a matched workflow was missing inputs, which template default got applied
could depend on Python's hash order (a fill loop removed items from the list it
was walking), the log promised "using defaults" at a point where no default
could exist, and the same missing input was reported twice. Defaults now fill
first, the per-variable repair only handles inputs without one, and a single
line says what actually happens: the turn falls back to the agent. -
German answers are asked to use real umlauts again. For a while the assistant
had taken to writing "fuer" and "laeuft" instead of "für" and "läuft", sometimes
switching between both inside one sentence. That comes from the language model, not
from VAF, and it feeds itself: the model reads its own earlier replies and copies the
habit. The instruction VAF sends with every turn now asks for proper German spelling
explicitly, which curbs it. It will not be perfect, and a fresh chat shows it best. -
A bundled browser script that nobody used is gone. It was a copy of a third-party
fingerprinting library, 43 KB, kept in the tree long after VAF stopped injecting it,
and it carried no author credit. Deleting it is the honest repair: nothing changes for
you, and one piece of somebody else's code no longer travels with every download. -
The bundled PDF viewer now ships the license it is used under. VAF includes a copy
of Mozilla's pdf.js worker so documents can be displayed; its license asks that
recipients get the license text itself, and that text is now included rather than only
linked. -
A comment claimed the recommended voice model was Apache-licensed. It is not. The
Gemma weights come under Google's own terms with usage restrictions. VAF never shipped
the weights and still downloads them only when you choose that model, so nothing about
your install changes - but the note in the code was wrong and is corrected. -
Setting the sub-agent timeout to "no limit" no longer arms a zero-minute
timeout. The row stored 0 minutes while the timeout stayed switched on - and a
zero-minute timeout means every running sub-agent is stopped at the next cleanup
pass. Choosing "no limit" now switches the timeout off, exactly as the classic
menu always did, and choosing a duration switches it on. -
The microphone list selects the device you picked. The classic picker
numbers the list by position, but the list is filtered - so on machines with
virtual audio devices the position could name a different microphone than the
one shown. The terminal app reads the device number printed in each entry. -
A long conversation no longer animates dozens of invisible dots. Every reply
in the terminal app carries the agent's living dot, but only the newest one shows
it - the hidden ones kept animating anyway, ten times a second each, so a long
session burned more and more CPU drawing into nothing. The visible dot animates
exactly as before; the hidden ones now rest until it is their turn again. -
vaf updatenow tells you why it could not answer. Three different situations
used to collapse into one sentence, "offline, or none published yet", whose two
halves call for opposite reactions. The real case that exposed it was neither:
GitHub allows unsigned-in requests only 60 per hour for a whole network address,
so any busy tool on the same connection could make the updater claim there was no
release minutes after one went live. It now says which it is - rate limit (with
the time to try again), unreachable, or genuinely no release - and a plain
permission error is not dressed up as a rate limit.
Security
- DOMPurify updated (3.4.13). A sanitizer bug could leave a removed
element's hidden children able to run scripts in applications that use one
specific advanced mode. VAF's interface never uses that mode - the library
only arrives through the code editor and the PDF export - so no VAF
installation was exposed; the update keeps the dependency clean regardless. - PostCSS updated (8.5.26). The build toolchain's CSS processor could be
tricked into reading arbitrary.mapfiles when it processes CSS from an
untrusted source without a known input file, disclosing their contents in
the generated source map. VAF only ever runs it over its own stylesheets at
build time, so no VAF installation was exposed - the update keeps the
dependency clean regardless. - js-yaml updated (4.3.1). The YAML parser that the linter uses to read its
own configuration resolved ordered maps in quadratic time, so a crafted
document could stall the process that parses it. It reaches VAF only as a
build-time dependency of ESLint and never sees anything but VAF's own config
files, so no VAF installation was exposed - the update keeps the dependency
clean regardless.