flowrs-engine/crates/flowrs-openui/README.md
flowRS fd958c0547 flowRS engine, cut from flowRS 3451b065
Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-11-02 19:04:39 -05:00

61 lines
3 KiB
Markdown

# 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.**
(<https://github.com/thesysdev/openui>), 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.