Agent-First UI v0.9.0: Trust Belongs to One Checkout

by Agent-First Kit Contributors

Trusting a workspace frontend now trusts that directory and no other, so two checkouts no longer revoke each other. A remote Provider can take as long to answer as the viewer is willing to wait, a minimised macOS window no longer ends its question, and the remote view and ask page speak Traditional Chinese.

A workspace frontend is code that runs in the person’s browser with the session’s credential, so AFUI renders one only after someone has said, once, that they trust it. Until now that trust had one key per provider. Two checkouts of the same project shared it: enabling the frontend in one replaced the trust of the other, and disabling either revoked both. This release keys trust by the frontend’s resolved directory, and fixes a set of places where a session ended, or failed, for a reason that had nothing to do with the person.

Trust per directory

afui frontend enable records trust for the directory it resolved, and afui frontend disable removes only that record. Another checkout keeps its own, and deleting a frontend directory no longer leaves a trust record that disable cannot reach. Both commands update trust.json under a lock and through a uniquely named temporary file, so two of them run at once no longer lose one write.

Trust recorded by earlier versions is keyed the old way and is not read. Run afui frontend enable once in each workspace you use.

A remote Provider can be slow

The remote view’s proxy gave a Provider five seconds to start answering. The same five seconds bounded connecting, which is right: a Provider that cannot be reached should be reported quickly. Answering is different. A route that renders a report or waits on a database worked in a local window and answered 502 remotely.

Only reaching the Provider is bounded now. Once a request is delivered, the proxy waits for as long as the viewer does. A viewer that gives up still closes the request’s connection to the Provider, so an abandoned request does not hold anything open. Ending a session keeps a five-second budget of its own.

Sessions that ended for the wrong reason

  • A minimised window. On macOS, minimising the window or hiding the browser ended the question as closed, as if the person had dismissed it. Only closing the window ends it now.
  • A slow host. The session registry deleted an entry whose host did not answer a liveness probe in time, even while the process that announced it was still running. An entry is now removed only when its owner process is gone; an unreachable host is hidden from one listing and shown again in the next.
  • A late completion. A completion handle kept after its ActiveUiSession was dropped could still record an answer nobody would read. Dropping the session closes its slot, and a late complete() reports false.
  • A killed collector. afui ask wait claims a result before reading it. A collector killed after the claim left a marker that kept every later ask wait from collecting. The next one takes the claim over. The claim itself is now a file created with create_new, which has one winner on every platform; the rename it replaces could move a result out from under a collector on Windows.

Traditional Chinese

The remote view and the ask page already spoke English and Simplified Chinese. A browser asking for zh-TW, zh-HK, zh-MO, or any Hant tag now gets Traditional Chinese controls in Taiwan usage. zh-Hans-HK and other Chinese tags stay Simplified, and Accept-Language weights are read case-insensitively, so zh;Q=0 really excludes Chinese.

Smaller fixes

  • The tojson template filter is gone, as safe already was. Its output was not escaped, so a value placed in an attribute could add attributes.
  • requires_elements and requires_element_map add to a decision contract instead of replacing it.
  • A redirect from a Provider to its own address — relative, or absolute with the upstream’s host — keeps its target and loses only the announced query. The proxy also drops response headers that Connection names.
  • Mount and advertised authorities are lowercased, matching what browsers send.
  • Decision declaration, route, and attribute errors carry the rule they broke, as Error::InvalidDecision, instead of the provider-id grammar.
  • afui.autosave recovers when save() throws synchronously.

Breaking changes

  • Frontend trust is per workspace directory. Trust recorded by earlier versions is ignored; enable each workspace again.
  • afui frontend diff no longer accepts --scope, which it ignored.
  • Error::InvalidDecision is a new variant, so an exhaustive match on Error needs an arm for it.
  • test_support::FrontendOnDisk::at takes the frontend root alone.
  • The tojson filter is removed from page templates.

Also in this release: AFUI moves to agent-first-data 0.36.1 and agent-first-slug 0.9.0.

Getting it

$ brew install agentfirstkit/tap/afui
$ cargo install agent-first-ui