Four bugs users were hitting on 0.15.5, the provider routing they came out of,
and a graphical client for people who would rather not live in a terminal.
Roadmap note. The 0.15.5 notes put Windows and macOS computer use in 0.16.0
and 0.16.5. That work ran into problems that took longer to sort out than
expected, and the defects fixed below were affecting live runs — so those went
first. Windows and macOS computer use is definitely still coming, in one of the
next few releases. No version number against it this time, given what the last
estimate turned out to be worth.
Fixed — defects that were affecting real runs
-
Gemini 2.5 model ids no longer work and were still being shipped. Google
keeps listing them, butgenerateContentanswers 404 "no longer available to
new users". A listing is not an entitlement. Anyone who picked Gemini in the
wizard had a configuration that could not work. Replaced with the 3.x line,
every id confirmed against a live call rather than a catalogue, and the
pricing table follows. -
BytePlus and FPT models were being sent to DeepSeek. Both resell other
vendors' models under their own gateway, so their catalogue ids are bare
vendor names —deepseek-v4-flash-ga-260813,DeepSeek-V4-Flash. Neither had
a routing prefix, so choosing one produced an id that routed to DeepSeek's own
API with a DeepSeek key: wrong endpoint, wrong bill, and an error blaming the
wrong provider. -
deepseek/deepseek-v4-proran against a 128k context instead of its real
1M. The routing prefix was missing from the strip regex, so the registry
lookup failed and every caller fell back to a 128k default — compacting about
eight times earlier than necessary. The bare id was unaffected, which is why
it stayed hidden. -
The setup wizard told people to retype a valid key. Every connection
failure offered "re-enter API key". OpenAI answers an unpaid account with 429
"exceeded your current quota", OpenCode Zen with 401 "Insufficient balance", a
retired model with 500 — none of which a different key can fix. Failures are
now classified (auth, billing, rate, model, server, network) and each leads
with the remedy that can actually help, saying plainly when the key is not the
problem. -
Pasted text and mouse reports could land in the model picker's filter. A
paste arrives wrapped in bracketed-paste markers and a mouse report as
\x1b[<b;x;yM; both decode to keypresses whose text is printable, so their
bytes were typed into the filter box.
Changed — one provider table instead of five
factory.ts described the same providers five separate times: the strip regex,
the API key resolver, the family resolver, the reverse base-URL map, and a
~320-line chain of construction branches. Nothing forced them to agree, and two
of the bugs above are what that drift looks like from the outside.
There is now one descriptor table, and all five views derive from it. Adding a
provider is a single entry. createProvider drops from ~320 lines to 47.
Two tests hold it together: one asserts the five structures agree with each
other, the other that the user-facing catalogue agrees with routing at all —
every model of all 31 routing targets resolves to its own provider's key.
Added — a web client
aura serve already spoke the full protocol over its WebSocket; what was
missing was a client. React, building to dist/web, served by the same command.
Streaming turns, markdown with copyable code, stop and regenerate, a
conversation sidebar, inline tool calls and approval prompts, a provider picker
across 28 providers with an API-key field when one is missing, tool toggles that
actually reach the engine, live token and cost, dark and light, and a layout
that works on a phone over --lan or --tailscale.
Seven languages — English, Serbian (Cyrillic), French, Italian, Spanish, Arabic,
Russian — with Arabic driving real right-to-left through logical properties
rather than a transform.
The design mirrors the TUI: every colour is taken from the terminal palette.
Commands beginning with : run rather than reaching the model. Fourteen work in
the client; the rest are reported by name as terminal-only rather than silently
sent to the agent as a question.
Security
- Plugin install, plugin removal and API-key changes are off by default.
aura serveexposed them to anything holding the pairing token. Installing a
plugin downloads and runs code with the server's full privileges and no
sandbox, so under--lanor--tailscalethat turned any paired device into
remote code execution. All three now requireaura serve --allow-plugin-install; listing what is installed stays open. - A proven pairing token becomes an
httpOnly; SameSite=Strictcookie, so
the page's own asset requests authenticate. Without it every subresource 401'd
and the page rendered blank. - Model output is sanitised before rendering. The client renders markdown as
HTML, and on the agent path that output carries whatever a tool read off disk.
Raw HTML is disabled at the renderer and the result is scrubbed anyway, tested
against the actual vectors.
Added — measurement
- The escalation benchmark had never run. It was excluded from
npm test
correctly, being slow and live, but pinned to an account that later lapsed —
so it self-skipped, and a benchmark that skips is indistinguishable from one
that passes. First live result: 6.7% missed escalation, 0% false
escalation over 30 cases. Both misses are design-mode; retrieval was 15/15. - A Gazelle blind eval, because 26x fewer tokens was a cost measurement with
no quality number beside it. Blind-scored, labels stripped: 114x fewer
tokens, correctness a wash on conversational prompts and +2.89 on
questions needing tools, where the coder path ran out of room and answered
anyway. The judge saturated on helpfulness, so that half is reported as
unmeasured rather than as a result. - The cost ledger no longer counts an unbilled call as a measured zero. A
provider error or an exhausted balance is not evidence that the large model
would have cost nothing, and counting it that way reported the gate as a total
loss. - Recorded provider fixtures, one per wire format rather than one per
vendor: there are four formats behind thirty-one routing targets.
Also
- The verifier can run on a separate provider, so it stops marking its own
homework. - It now sees the evidence an answer is actually about — identifiers, paths,
line refs — rather than a flat 300-character head of each tool result, which
on a real file read was about 6% of the evidence, chosen without reference to
what was being checked. - A second training path writes direct correction pairs from escalation
episodes; every row carries its provenance so the two sources can be ablated
separately. Neither path runs automatically. docs/SANDBOX-DESIGN.md— a design for--sandboxed, a real out-of-process
boundary, with the mechanism verified but not yet implemented. The default
path remains a guardrail, and SECURITY.md still says so.