genui_gen 0.8.1
genui_gen: ^0.8.1 copied to clipboard
Annotations and runtime helpers to generate genui CatalogItems from your own Flutter widgets. Derive the schema from the constructor so the catalog can never drift.
0.8.1 #
- Documentation only; no API change.
- Corrected the install instructions. They still listed
json_schema_builderas a direct dependency and imported it in the annotated file, which stopped being true in 0.3.0 when this package began re-exportingS,SchemaandObjectSchemafor exactly that reason. - The README now covers what 0.4 through 0.8 added:
@GenUiWrites, child templates, lists of scalars and enums, and the assembledgenUiCatalogwith itscatalog_id. - Added
homepage, pointing at https://diegolopezrm.github.io/genui_gen/.
0.8.0 #
- Added
genUiTemplateChildrenandgenUiTemplatePath, the runtime half of child templates. A2UI describes the children of a component in two ways: a list of ids the agent wrote out, or{"componentId": "row", "path": "/rows"}repeated once per entry of the data model. The second is what makes a list that grows when the agent sends data rather than a new surface, and a generated widget could not accept it. - Each template child reads its own entry: the child of
/rowsat index 2 bindstitleagainst/rows/2/title, so one component describes every row. Children are keyed by entry rather than by position, so a row removed from the middle takes its state with it instead of handing it to the row below. - Added
GenUiBinding.valueandGenUiValues.raw, which resolve a path and hand back what it holds without coercing it. The typed bindings are right for a widget property; a template needs the list or the map itself.
0.7.0 #
-
Added
package:genui_gen/tracing.dart: record an agent session and replay it. A generative interface has a problem an ordinary app does not — the screen that failed is not in the source, because a model composed it once from a context that will not come back — and a trace is that session, kept.GenUiTraceRecorder.attachkeeps every message the agent sent, the contents of each surface's data model whenever they changed, and every action the app sent back;GenUiTracePlayerreplays it with no model and no network, andGenUiTraceViewshows it, at any step.final player = GenUiTracePlayer(trace, catalog: genUiCatalog)..seek(7); await tester.pumpWidget(MaterialApp(home: GenUiTraceView(player: player)));Because the replay renders against the app's current catalog, an old session is also a regression test: a catalog change that breaks a real conversation fails before a user finds it.
-
redactnames the data model paths a recording must not keep. A session records what the user typed, so the field holding an email has to be named before the first recording rather than after the first leak. -
Added
genUiCatalogDiff, which reports what changed between two catalog documents from where it matters: the model. A removed component, a new required property, a dropped enum value and a changed type are breaking, because the agent's prompt still describes the old one. A new optional property and a new enum value are not. -
Added
genUiSemanticsAudit, which reads the recording the golden test already keeps and reports what a screen reader user could not work with: a control with nothing to announce, a component that reaches assistive technology as nothing at all, two controls that announce themselves identically. -
Added
genUiCatalogWeight, which says how much of every prompt each component takes up. A catalog is sent on every request and nothing makes its cost visible. -
GenUiSemanticNodenow recordstooltipalongsidename. A control named only by a tooltip is not unnamed, but it is not named the same way either, and the recording shows which of the two it has. -
The example app records a session with its own widgets, checks its catalog against the published one, and lists what the basic catalog gives a screen reader today: an audio player whose play button and two sliders announce nothing, an image that exposes nothing at all, and a slider with a
labelthe catalog never passes on.
0.6.0 #
-
Added
package:genui_gen/testing.dart, which checks the half of a catalog the schema cannot: what a generated component actually exposes to the person using it.genUiSemanticsreads the role, name, value, state and actions of a rendered surface, in traversal order;genUiSemanticsGoldenrecords that into a JSON file and fails when it changes;GenUiExampleSurfacerenders one item's generated example through a realSurfaceController, so the test covers the whole path — schema, bindings and actions — rather than the widget alone.expect( genUiSemanticsGolden(recorded, File('test/genui_semantics.json')), isNull, ); -
The recorded file is checked in and read in review. It is the answer to "what can the model make this app announce, press or report", which is the part of a change that a Dart diff does not show. Re-record a deliberate change with
GENUI_UPDATE_GOLDENS=1. -
The file is written in the shape A2UI's rendering cases use — role, name, value, state, actions — so the same recording describes the catalog to a renderer on another platform.
-
example/test/genui_semantics.jsonrecords the example app's catalog, andexample/test/genui_semantics_test.dartis the test to copy. -
a2ui_coreis now a dependency:GenUiExampleSurfacebuilds the surface from the same message types genui takes.
0.5.0 #
-
Added
genUiCatalogJsonandgenUiCatalogJsonString, which turn aCataloginto the A2UIcatalog.jsondocument that describes it. Inside the app genui puts the catalog in the prompt for you; everything outside this Flutter process needs it as a document — an agent written in Python, a second client rendering the same surfaces in SwiftUI, a review that has to answer what the model was allowed to ask for last Tuesday. The result is the shape A2UI publishes for its own basic catalog:catalogId,components,functionswhen the catalog has any, and the$defsa renderer resolves a component against.final json = genUiCatalogJsonString(genUiCatalog, title: 'Acme catalog'); -
The export takes a
titleand adescriptionof its own. genui fills inA2UI CatalogandCustom catalog of A2UI components and functions.for every catalog ever generated, and an agent handed three of them has nothing else to tell them apart by. -
A catalog with no
catalogIdis rejected rather than exported. A surface names the catalog it was built against, so a document without an id describes components that nothing can ask for. -
example/catalog.jsonis generated from a test, and the README shows the pattern: write the file under--update-goldensand compare against it otherwise, so the document in the repository cannot fall behind the widgets and a reviewer sees what a new@GenUiWidgetexposed to the model.
0.4.0 #
- Added
@GenUiWrites, which makes a control the user operates annotatable. Avoid Function(T)parameter marked@GenUiWrites('<property>')receives a callback that writes the user's value into the surface's data model, at the path the model bound<property>to. It is what genui's ownTextField,Slider,CheckBox,ChoicePicker,DateTimeInputandTabsalready do, and until now an annotated widget had no way to express it: a property was read-only, so a switch or a text field could not be annotated at all.Tmay be aString, anint, adouble, anum, aboolor an enum. - A property some callback writes to is now read back through the same path it
is written to, so the control reflects what the user just did. A literal the
model sent is still honoured until that path holds something, the way
TextFieldseeds itself from its initial value. When the model sends a literal rather than a binding there is no path it named, so the value is written to<componentId>.<property>— the fallback the core catalog uses — and the control stays interactive. - The description of a written property gains a sentence saying so. The callback itself is not in the schema, because the model never supplies it, so the model would otherwise have no way to know that binding the property to a path is how it reads the answer.
- Added the runtime helpers
genUiValueWriter,genUiWritePathandgenUiWriteReference, called by generated code. A write the data model refuses — a non-numeric segment on a list, an index out of bounds — is reported throughctx.reportErrorrather than thrown out of a gesture handler, exactly as a failed action is. - The callback's argument may not be nullable. A2UI has no agreed meaning for
writing
nullto a path, soValueChanged<String?>is a build error rather than a silent choice between "clear it" and "store null". - Additive release: a widget that uses only 0.3 types generates identical code.
0.3.0 #
- Added lists of scalars: a
@GenUiWidgetparameter or@GenUiDatafield may now be aList<int>,List<double>,List<num>, or aList<E>for an enumE. Each was a build error in 0.2. - Added
GenUiBinding.numberListandGenUiValues.numberList, resolved through genui'sBoundList. Entries that are not numbers are dropped, and a numeric string is parsed, the way the core catalog's number binding does. - Added the coercion helper
genUiAsNumList, used by generated decoders for numeric list fields of a@GenUiDataclass. - A list of enums is carried as strings and mapped back by name. A name the enum does not declare is dropped rather than defaulted: the list is the model's, and one bad entry should not silently become a value the author never wrote.
- Re-exported
S,SchemaandObjectSchemafromjson_schema_builder, so an annotated file importsgenui_genalone andjson_schema_builderstops being a direct dependency of consumers.shown rather than exported wholesale; ifScollides with another one-letter name, import withhide S. json_schema_buildermoved from dev_dependencies to dependencies, since those three names are now part of this package's public API.- Additive release: widgets that only use 0.2 types generate identical code.
0.2.0 #
- Added
@GenUiData, marking a plain Dart class as a data shape an annotated widget may receive. A@GenUiWidgetparameter may now be a data class, or aListof one, so widgets that take rows, points or items are annotatable. - Added the
GenUiDecoder<T>typedef used by generated code to rebuild a data class from the map the model produced. - Added
GenUiBinding.objectandGenUiBinding.objectList, resolved through genui'sBoundObjectandBoundList, plus the matchingGenUiValues.objectandGenUiValues.objectListaccessors.objectListskips entries that are not maps instead of throwing. - Added the coercion helpers
genUiAsString,genUiAsNum,genUiAsBool,genUiAsStringList,genUiAsObjectandgenUiAsObjectList. Generated decoders call them instead of casting, so a field of the wrong type degrades the way genui'sBound*widgets degrade instead of throwing aTypeErrorinsidebuild. - Added
GenUiMissingFieldReporter,genUiMissingFieldandgenUiNestedField, which carry the missing-property report into a data object: a required field the model left out of a row reaches the model asrows.label. - Additive release: widgets that only use 0.1 types generate identical code.
0.1.2 #
- Version bump to stay aligned with
genui_gen_builder0.1.2. No API changes.