# flowrs-openui OpenUI Lang 1.0 in pure Rust: the lexer, parser, streaming parser, evaluator, edit merge, serializer, validation rules, and a headless runtime (state, forms, actions, queries, mutations, host events). flowRS's app layer (`flowrs-app`) writes and checks apps in it; the renderer draws the tree this crate evaluates. ## Licence MIT OR Apache-2.0, at your option (`LICENSE-MIT`, `LICENSE-APACHE`; third-party material in `NOTICE`). ## Attribution OpenUI Lang and its reference implementation are by **Thesys Inc.** (), under the MIT licence (`LICENSES/OpenUI-MIT.txt`, "Copyright (c) 2011-2024 Thesys Inc."). This crate is a port, not a fork. It follows the 1.0 specification (`spec/language.md`, `spec/overview.md`, `spec/prompt.md`) and ports the behaviour of `@openuidev/lang-core` 1.0.1 (`packages/lang-core/src`) to Rust; every source file names the files it was ported from. It does not depend on, or copy from, the `openui` crate (`openui-rs`). No `@openuidev` JavaScript is shipped or run. The conformance fixtures in `tests/fixtures/1.0` are copied unchanged from `spec/fixtures/1.0` at upstream commit `9d73d17d2bbac565672a85e78f6eb7740cb0d9ca` (2026-10-23), under the same MIT licence. ## Conformance `cargo test -p flowrs-openui` runs all 59 fixtures: every program case at level 1 (syntax, streaming, entry, references, evaluation, editing, errors, validation rules), and the 12 `interactions.json` cases at level 2 through `Session`. A property test feeds every fixture's text in thousands of chunkings and requires the same program a batch parse gives. ## Where this follows the spec text over the reference Each is noted in the file that does it. - **Fences** open only at the start of a line, and quotes in prose do not shield one (§1.2). The reference finds an opener anywhere. - **Statement boundaries** read brackets as a stack, so a mismatched closer does not close (§1.4 with §4 rule 2); the reference counts depth. Both batch and streaming use the stack, so they agree on malformed input too. - **Query and mutation arguments** resolve references like any expression, so what they name is reachable (§2.3, §6.1). - **Stream end** makes the pending tail final, a redefinition included (§4 rule 7), so a stream always equals a batch parse. - **The edit merge** reads both texts with §1.2 and §1.4, multi-line ternaries included (§7). - **Data never becomes an action**: only an action call makes a plan. ## Extensions - `Library::data_refs`: names a host binds as data (flowRS: graph ports, `n7.mean`). A reference to one that no statement defines reads `Host::reference` instead of being unresolved. A spec client without the extension sees an unresolved name and renders nothing there. - Nesting is bounded (`MAX_DEPTH`), and `pattern` runs on a small matcher with a step budget: model output is untrusted. - Tools are synchronous (`Tools`); an asynchronous host answers from what it holds and calls `Session::refetch` when a result arrives.