openui_core 0.0.1-dev.2 copy "openui_core: ^0.0.1-dev.2" to clipboard
openui_core: ^0.0.1-dev.2 copied to clipboard

Pure-Dart core for OpenUI Flutter: lexer, parser, AST, streaming parser, evaluator, reactive store, library DSL, action steps, and tool-provider interface. The language layer that the Flutter renderer [...]

openui_core #

Pub License: MIT style: very_good_analysis

Pure-Dart language core for the OpenUI Flutter port. Lexer, parser, evaluator, reactive store, library DSL, action dispatcher, tool-provider interface, and JS-compatible integration entry — everything OpenUI Lang needs that does not touch Flutter.

Runs in any Dart context — a Flutter app, a server, a Cloudflare Worker, a CLI. The openui (Flutter) and openui_components packages sit on top.

Install #

dependencies:
  openui_core: ^0.1.0

Status #

v0.1 is in active development. Phase 1 is complete: 461 tests, 100% line coverage across 16 source files. All public symbols carry @experimental per Decision D12.

Public API #

The barrel lib/openui_core.dart is the only file consumers should import. Everything under lib/src/** is private.

Parser #

final program = parseProgram(source, recoverable: true);
final expr = parseExpression(source);
final closed = autoClose(partialSource);

Sealed AstNode hierarchy (Literal, Reference, StateRef, StateAssign, ArrayLit, ObjectLit, BinaryOp, UnaryOp, Ternary, MemberAccess, IndexAccess, CompCall, BuiltinCall, MutationCall, NullLiteral) plus Statement / StatementKind and classifyStatement.

Streaming parser #

final parser = createStreamingParser(rootName: 'root');
final result = parser.push('root = Stack([\n  Card()\n');
// `result.meta.incomplete` flags in-flight statements;
// `meta.unresolved` lists unbound references;
// `meta.orphaned` lists unreachable value statements;
// `meta.stateDecls` / `meta.queries` / `meta.mutations` carry
// declarations; `result.root` is the materialized entry point.

Materializer #

final res = materialize(
  rootName: 'root',
  statements: program.statements,
  incomplete: const {'root'},
);
res.root;        // ElementNode? at the entry point
res.unresolved;  // List<String>
res.orphaned;    // List<String>

Integration entry — parse(source, paramMap) #

Mirrors the JS reference's parse(input, cat, rootName?). Builds a fully- resolved ResolvedElement tree in one pass, including required-prop validation and UnknownComponentError reporting.

final paramMap = <String, List<ParamSpec>>{
  'Stack': [const ParamSpec(name: 'children', required: true)],
  'Title': [const ParamSpec(name: 'text', required: true)],
};

final result = parse('root = Stack([Title("hi")])', paramMap);
result.root!.typeName;             // 'Stack'
result.root!.props['children'];    // List<ResolvedElement>
result.meta.errors;                // List<OpenUIError>
result.meta.unresolved;            // List<String>
result.stateDeclarations;          // auto-declared $vars

Reactive store #

final store = Store()
  ..initialize({r'$count': 0})  // does not overwrite user-modified keys
  ..set(r'$count', 1);          // shallow-equality short-circuits no-op writes
final unsubscribe = store.subscribe(() => print('changed'));
store.dispose();                 // listeners cleared; further ops throw

Evaluator #

final ctx = EvalContext(
  statements: program.statements,
  store: Store()..set(r'$count', 3),
  builtins: functionalBuiltins,    // @Count, @Filter, @Each, @Map
);
evaluate(ast, ctx);                // Object?
ctx.errors;                        // CyclicStateError + EvaluationError

Action plan + dispatcher #

final plan = actionPlanFromAst(rhs)!;  // null unless rhs is a non-empty
                                      // [...] of action builtins only
await dispatchAction(
  plan: plan,
  context: ctx,
  stateDefaults: const {r'$count': Literal(0, offset: 0)},
  onRun: (id) async => queryManager.refresh(id),
  onOpenUrl: (url) => launchUrl(url),
  onContinueConversation: (msg, extraCtx) => controller.send(msg),
);

SetStep.valueAst is re-evaluated against the current store at click time (Decision D3).

mergeStatements #

final merged = mergeStatements(
  existing,
  patch,           // an LLM-emitted edit set
  rootId: 'root',
);

Strips Markdown fences, upserts patches, deletes NullLiteral statements, runs the orphan GC, re-emits with per-statement whitespace preserved.

Library and defineComponent #

final lib = Library<MyWidget>([
  defineComponent<MyWidget>(
    name: 'Input',
    schema: Schema.object(properties: {
      'value': reactive(Schema.string()),  // marks as two-way bound
      'placeholder': Schema.string(),
    }),
    render: (ctx, props, renderNode, statementId) => MyWidget.input(props),
  ),
]);

final props = evaluateElementProps(
  call: compCall,
  schema: lib['Input']!.schema,
  context: ctx,
);
// Reactive props bound to `$state` arrive as `ReactiveAssign(target, value)`
// markers; check via `isReactiveAssign(value)`.

Tool provider #

class MyProvider implements ToolProvider {
  @override
  Future<Object?> callTool(String name, Map<String, Object?> args) async {
    final raw = await transport.call(name, args);
    return extractToolResult(
      ToolResult(text: raw.body, isError: raw.statusCode >= 400),
    );
  }
}

Error vocabulary #

OpenUIError is sealed. Subclasses: ParseError, EvaluationError, CyclicStateError, UnknownComponentError, McpToolError, ToolNotFoundError, AdapterMismatchError. Each carries code, optional message / hint / statementId, and structural equality.

Layout #

lib/src/
├── parser/    lexer, AST, parser, statements, streaming, materialize
├── parse/     integration entry, ResolvedElement, ParamMap
├── state/     reactive Store
├── eval/      evaluator + functional builtins
├── library/   Component, Library, reactive, evaluateElementProps
├── actions/   ActionStep, ActionPlan, dispatcher
├── merge/     mergeStatements
├── errors/    sealed OpenUIError hierarchy
└── tools/     ToolProvider, ToolResult, extractToolResult

See docs/lang-reference.md for the language grammar and docs/architecture.md for the package map and data flow.

License #

MIT — see LICENSE.

0
likes
140
points
208
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Pure-Dart core for OpenUI Flutter: lexer, parser, AST, streaming parser, evaluator, reactive store, library DSL, action steps, and tool-provider interface. The language layer that the Flutter renderer sits on top of.

Homepage
Repository (GitHub)
View/report issues
Contributing

License

MIT (license)

Dependencies

collection, json_schema_builder, meta

More

Packages that depend on openui_core