GenUI
Parser, validator, and store
The pieces GenUI is built from, for validating on a server, testing prompts, or building your own renderer.
Parse a partial response
parsePartialJson parses any prefix of a JSON document into the best complete tree. Open strings, arrays, and objects are closed, a key without a value is dropped, and half-written escapes, numbers, and literals are not guessed at. It never throws.
Nesting deeper than 100 levels and text beyond 2 MB are cut off, numbers beyond the double range become null, lone surrogates are repaired, and __proto__ is an ordinary key.
import { parsePartialJson } from "@comp0/genui";
const parsed = parsePartialJson('{"type": "Stack", "children": [{"type": "Text", "text": "Hel');
parsed.value; // { type: "Stack", children: [{ type: "Text", text: "Hel" }] }
parsed.open; // Set { "", "/children", "/children/0", "/children/0/text" }
parsed.complete; // false| Prop | Type | Description |
|---|---|---|
final | boolean | The text will not grow: a number that ends it is complete, and trailing content is reported. Defaults to false. |
| Field | Type | Description |
|---|---|---|
value | JsonValue | undefined | The best tree for the text so far; undefined while no value has started. |
complete | boolean | The document is a closed value with nothing but whitespace after it. |
open | ReadonlySet<string> | JSON Pointers of the values that may still grow. The root is the empty string. |
issues | readonly ParseIssue[] | Syntax the parser cannot recover from, with path, message, and offset. Everything before an issue is still returned. |
Validate on a server
validateResponse takes text, a PartialParse, or an object, and returns the component tree to render with every node keyed by its JSON Pointer, the errors, and the declared bindings. validateNode does the same for one finished object.
import { formatErrors, validateResponse } from "@comp0/genui";
const { errors } = validateResponse(text, { complete: true });
if (errors.length > 0) await askAgain(formatErrors(errors));| Prop | Type | Description |
|---|---|---|
catalog | readonly CatalogEntry[] | The components a response may use. Defaults to the built-in catalog. |
complete | boolean | Whether the response is finished. While it is not, nothing is reported. Defaults to true. |
known | Iterable<string> | Names that already have a value, such as the keys of a saved state; expressions may read them. |
| Field | Type | Description |
|---|---|---|
root | ValidNode | undefined | The component tree to render: each ValidNode has its key, catalog entry, and surviving props. |
errors | GenUIError[] | Problems to send back to the model; always empty while the response streams. |
complete | boolean | Whether the response was finished when it was validated. |
bindings | ReadonlyMap<string, JsonValue | undefined> | Every binding name the response declares, with the first initial value written for it. |
- Validated props hold a
Binding(withnameandinitial) for every$bindand aComputed(with the parsedexpressionand itssource) for every$expr.
Evaluate an expression
parseExpression returns { ok: true, expression } with the names the expression reads, or { ok: false, message, position }. evaluateExpression takes the source or a parsed expression and the values by name, as an object or a function. expressionFunctions lists the functions with their summaries.
import { evaluateExpression, parseExpression } from "@comp0/genui";
evaluateExpression("round(seats * 1.5, 2)", { seats: 3 }); // 4.5
parseExpression("seats *"); // { ok: false, message, position }Keep state in a store
createGenUIStore(initialState?) is the external store the controls and results read with useSyncExternalStore, so a change re-renders exactly the parts that read it. Entries of the initial state that are not JSON values are ignored.
| Method | Type | Description |
|---|---|---|
get | (key: string) => JsonValue | undefined | The stored value, or undefined when nothing is stored under the key. |
getSnapshot | () => GenUIState | Every stored value; the same object until something changes. |
set | (key: string, value: JsonValue | undefined) => void | Stores a value as an edit. undefined removes the key. |
seed | (key: string, value: JsonValue) => void | Stores a default only when nothing is stored under the key. It notifies readers but is not an edit. |
subscribe | (listener: () => void) => () => void | Calls listener after every change, including seeds. |
subscribeToEdits | (listener: (state: GenUIState) => void) => () => void | Calls listener with a snapshot after every edit. |
Helpers
Small functions the renderer uses, exported for hosts that build around it.
formatErrors(errors)writes the repair message for a list ofGenUIErrors.describeFormValues(fields, values)describes form values in the words on the screen:Plan: Pro; Seats: 5.safeHref(value)returns a link target that is safe to use, orundefined;isSafeHref(value)says whether it is.safeImageSrc(value)returns an image source that is safe to load, orundefined.describeCatalog(catalog?)describes a catalog as plain JSON: every component with its group, description, and props.