Skip to content

AgentOS 2026.8.15

Choose a tag to compare

@github-actions github-actions released this 15 Aug 18:10
· 448 commits to main since this release
9d4e460

A search-and-Web-UI release. web_search gains Tavily as a built-in runtime provider, the Web UI finally tells you when a new release is out — the CLI has done that for several versions — and every sidebar view becomes reachable from the keyboard through Gmail-style g chords.

Added

  • A built-in Tavily provider for web_search. Tavily was previously reachable only through the multi-search-engine skill, which shells out to a script. It is now a runtime provider registered next to brave and duckduckgo, so selecting tavily and setting TAVILY_API_KEY is the whole setup — no skill, no subprocess. Onboarding lists it alongside the other keyed providers, the tool wires the configured key through the same path Brave uses, and errors map onto the shared taxonomy: 401/403 become non-retryable auth, 429 becomes rate_limit, timeouts stay retryable, so provider fallback behaves the way it does for every other backend. tvly- keys are redacted in logs and transcripts.

  • A "new release available" banner in the Web UI. The CLI has warned about outdated installs for several releases; the browser console said nothing, so anyone who lives in the Web UI never learned an upgrade existed. An updates.check RPC method — control audience only — returns the running version, the latest version on PyPI, and a status of up-to-date, outdated or offline; the console renders the banner only on outdated.

    • It reuses the CLI's cached PyPI state rather than adding its own polling. The check writes into the same notice-state file under a separate webui slot, so opening the console does not put extra traffic on PyPI beyond the interval already in place, and the PyPI call is capped at a 2s timeout on a worker thread so a slow or unreachable index degrades to offline instead of hanging the RPC.

    • The existing opt-outs keep working. AGENTOS_NO_UPDATE_NOTICE=1 and updates.notify = false both short-circuit the check before any network call, and the handler returns offline with no latest — the banner stays hidden, and the preference does not have to be set twice for two surfaces.

    • pypi_client and version_utils moved from agentos.cli to agentos.compat, so the gateway can check versions without importing the CLI. The import-contract test enforces the boundary rather than trusting it.

  • g-prefixed navigation chords in the Web UI. Press g, then a destination key within 1.5s: g c chat, g o overview, g h health, g n channels, g m MCP, g k skills, g s sessions, g a agents, g u usage, g r cron, g e env, g l logs, g p approvals, g , settings — fourteen views, all reachable without the mouse. The pending prefix re-arms on a repeated g and is cancelled by Escape or any held modifier, so a chord in flight never eats a real shortcut. Each jump closes the mobile drawer and moves focus to #main-content, so keyboard and screen-reader users land where they navigated instead of at the top of the sidebar. The ? cheat sheet renders multi-step chords with a localized "then" separator, and docs/web-ui.md documents the full set.

Fixed

  • The per-message hover toolbar could not be clicked. Copy, regenerate and edit sit in the outer gutter at left: 100% plus an 8px margin — entirely outside the .msg box that carries the :hover state. Moving the pointer from the bubble toward the buttons crossed that dead strip, dropped the hover, and faded the toolbar out before it could be reached; the reveal animation compounded it by sliding the buttons away from the incoming cursor. A transparent 10px pseudo-element now bridges the gutter back to the bubble edge, mirrored per role, and inherits pointer-events from the toolbar so it stays inert while the toolbar is hidden or the message is still streaming. The translateX reveal is gone, so the target no longer moves. Measured with elementFromPoint against the built stylesheet: the path from bubble edge to copy button has 0 dead pixels with the bridge and 8 without, on both sides. The bridge is suppressed at ≤ 560px and under hover: none, where the toolbar is already in normal flow and a strip in the margin would only swallow taps.

  • A coarse clock could stretch the x_search budget. The per-attempt timeout came from deadline - time.monotonic(), where deadline is itself time.monotonic() + total_timeout_seconds. Linux resolves monotonic() to nanoseconds, so the second read is always later and the remainder lands under the budget. Windows resolves it to ~15.6ms, so both reads routinely fall in the same tick and the expression collapses to a rounded (t + 20.0) - t — which for many values of t evaluates just above 20.0, handing one attempt a timeout fractionally larger than the total budget it was supposed to fit inside. The per-attempt timeout is now capped on the total budget as well as on the remainder, so the invariant holds at any clock granularity. The regression test pins monotonic() to a value where the sum is known to round up, reproducing on any platform what CI hit only intermittently.


Full changelog: v2026.8.13...v2026.8.15