Tesserae.A2UI 26.11.8018

dotnet add package Tesserae.A2UI --version 26.11.8018
                    
NuGet\Install-Package Tesserae.A2UI -Version 26.11.8018
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Tesserae.A2UI" Version="26.11.8018" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Tesserae.A2UI" Version="26.11.8018" />
                    
Directory.Packages.props
<PackageReference Include="Tesserae.A2UI" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Tesserae.A2UI --version 26.11.8018
                    
#r "nuget: Tesserae.A2UI, 26.11.8018"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Tesserae.A2UI@26.11.8018
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Tesserae.A2UI&version=26.11.8018
                    
Install as a Cake Addin
#tool nuget:?package=Tesserae.A2UI&version=26.11.8018
                    
Install as a Cake Tool

tesserae-a2ui

Tesserae.A2UI renders A2UI (Agent-to-User Interface) v1.0 messages as a live Tesserae user interface. An agent streams JSON (createSurface, updateComponents, updateDataModel, deleteSurface); the host keeps a real interface in step with it, two-way binds the user's input to a data model, and sends what the user does back as protocol messages. It is C# compiled to JavaScript with the Transpose compiler, depends on Tesserae only, and has no JavaScript of its own.

  • The protocol, all of v1.0: surfaces, adjacency-list component trees that fill in progressively (a child can arrive after its parent), createSurface with components and data model in one message, JSON Lines / array / single-envelope input, callRendererFunction / callAgentFunction and their responses, sendDataModel, the protocol's error codes.
  • A reactive data model: JSON Pointer paths, upsert and delete semantics, relative paths and @index inside templates, formatString with nested ${...} expressions, and bindings that re-evaluate only when data they read changes.
  • The basic catalog: all 18 components drawn with Tesserae components (see the table) and all 14 functions, with @checks validation (inputs show the first failing message once touched; a Button with a failing check is disabled), the A2UI regex dialect with its backtracking safety check, media URL rules, accessibility attributes.
  • Your own catalogs: register components and functions under a catalog id, mix catalogs in one surface with @catalogId.
  • A sample gallery with every example from the A2UI specification drawn next to the messages that produce it, a playground, guides, and a Playwright suite (every example, the interactions, 15 themes in light and dark).

See CLAUDE.md for how the repository works and TODO.md for what is not done. The upstream A2UI repository this was built against is kept, unmodified, in .reference/ (its CI is disabled there).

Use

// once, before the first use (the package's JavaScript is loaded on demand):
await Transpose.Require.RequireAsync(Transpose.RequireKind.Module, "./Tesserae.A2UI.js");

var host = new A2UIHost()
    .OnAction(a => SendToAgent(a.ToEnvelope().ToJson()))       // the user pressed a Button with an action.event
    .OnError(e => Log(e.ToString()));                          // anything the renderer could not do

host.Process(jsonlFromTheAgent);                               // JSON Lines, an array, or one envelope; call it again for every chunk
MountToBody(host.S());                                         // a host is an ordinary Tesserae component
Input Process(string) (any stream shape), Process(JsonValue), Process(A2UIMessage), ProcessAsync(text, delayMs) (replay a stream), Clear()
Output OnAction(A2UIAction) (resolved context, optional DataModel for sendDataModel surfaces), OnMessage(envelope, metadata) (every renderer-to-agent envelope), OnError(A2UIError), OnProcessed(message)
Surfaces Surfaces, GetSurface(id), surface.Data (a DataModel: Get(path), Set(path, value), Changed), surface.GetComponent(id)
Catalogs RegisterCatalog(catalog), FallbackCatalog, BasicCatalog.Instance / BasicCatalog.Create()
Agent functions CallAgentFunctionAsync(surface, name, catalogId, args) sends callAgentFunction and awaits the agent's agentFunctionResponse (a function a catalog does not implement is routed here)

Basic catalog

Component Drawn with
Text MarkdownBlock (no links or embedded content); caption variant
Image Image with the six variants and fit; URL rules (http, https, data, same-host relative)
Icon Icon with the 60 catalog names mapped onto UIcons; {svgPath} icons
Row, Column Stack; justify, align, weight (flex with a zero basis, so columns line up); static children or a template over the data model
List a scrolling Stack, vertical or horizontal
Card Card
Tabs Pivot
Divider HorizontalSeparator, or VerticalSeparator for the vertical axis
Modal Modal opened by the trigger
Button Button (primary / borderless variants; a Text or Icon child becomes its label or icon); @checks disable it
CheckBox CheckBox
TextField TextBox (short, number, obscured) / TextArea (long)
DateTimeInput DatePicker, TimePicker, DateTimePicker; ISO 8601 in the data model
ChoicePicker ChoiceGroup (one), CheckBoxes (several), ToggleButton chips, an optional filter box
Slider Slider, mapped onto whole steps so decimal ranges work
Video VideoPlayer (native controls, poster); URL rules as for images
AudioPlayer AudioPlayer (waveform seek bar, native-controls fallback); description is its accessible name

Functions: required regex length numeric email formatString formatNumber formatCurrency formatDate (Unicode TR35 patterns) pluralize openUrl (user gesture only, http/https only) and or not, and the system function @index.

A custom catalog

var stars = new Catalog("https://example.com/catalogs/stars/1.0")
    .Component("Rating", cx =>
    {
        var rating = Rating(5);
        cx.Bind("value", v => rating.SetValue((int)(Coerce.ToNumber(v) ?? 0)));          // model -> view, live
        rating.OnChange(v => cx.WriteBack("value", JsonValue.Number(v)));                 // view -> model
        return rating;
    })
    .Function("shout", (ec, args) => JsonValue.String(Coerce.ToText(args.Get("value")).ToUpperInvariant() + "!"));

host.RegisterCatalog(stars);   // a component then says "@catalogId": "https://example.com/catalogs/stars/1.0"

Changing the basic catalog

Override, Decorate and OverrideFunction change the basic catalog, which is one shared instance, so they apply to every host:

host.Override("Divider", cx => HorizontalSeparator("replaced").Primary());               // replace a component
host.Decorate("Button", (cx, inner) => { var b = inner(); /* add to it */ return b; });  // wrap the original: bindings, checks and action stay
host.OverrideFunction("formatCurrency", (ec, args) => JsonValue.String("..."));          // replace a function

To change it for one host only, work on that host's own copy; to add a catalog id that starts from an existing one, Extend:

host.OwnCatalog().Component("Divider", cx => /* ... */ null);                            // a private copy, changed
var mine = host.Extend("https://example.com/catalogs/mine/1.0");                         // a new catalog id, starting from the basic one
mine.Component("Chart", cx => /* ... */ null);                                           // and add to it

Catalog itself has Component, Function, Decorate, DecorateFunction and Clone(newId) for building a catalog away from a host.

ComponentContext is what a factory is handed: Bind / BindString / BindBool (live properties), Watch (rebuild on change), WriteBack (two-way), Child(id) / Children(stack) (children, templates, progressive rendering), BindChecks (validation), RunAction (agent events and local functions). Everything it creates is released when the component is rebuilt or removed.

Build and run

dotnet tool update --global Transpose.Compiler
export PATH="$PATH:$HOME/.dotnet/tools"
dotnet build Tesserae.A2UI.slnx                       # Debug: one readable bundle; Release: minified, chunked
cd Tesserae.A2UI.Sample/bin/Debug/netstandard2.0/tps && dotnet serve --port 5000

cd Tesserae.A2UI.Sample/playwright && npm install && npx playwright install chromium && npm test

node scripts/make-sample-examples.mjs refreshes the gallery's example files from .reference/. Nothing is built for Node: the examples are fetched by the page.

Packaging

.azure-devops/build-nuget-transpose.yml builds Tesserae.A2UI with a CalVer version (yy.M.build) and pushes the package to NuGet. GitHub workflows run the Playwright suite on pull requests (tests.yml) and publish the gallery to GitHub Pages (pages.yml).

License

MIT, see LICENSE. The A2UI specification and examples in .reference/ are Apache-2.0 (see .reference/LICENSE).

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on Tesserae.A2UI:

Package Downloads
Curiosity.FrontEnd

Package Description

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
26.11.8018 0 11/13/2026
26.11.8017 0 11/13/2026
26.11.8010 0 11/13/2026
26.11.8008 0 11/13/2026
26.11.8007 0 11/13/2026
26.11.8005 0 11/13/2026
26.11.8002 0 11/13/2026
26.11.7992 0 11/12/2026
26.11.7988 0 11/12/2026
26.11.7987 0 11/12/2026
26.11.7985 0 11/12/2026
26.11.7983 0 11/12/2026
26.11.7981 38 11/12/2026
26.11.7980 36 11/12/2026
26.11.7978 42 11/12/2026