openui_core 0.0.1-dev.1
openui_core: ^0.0.1-dev.1 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 [...]
0.0.1-dev.1 #
- BREAKING:
Query(name: ..., args: ...)is removed. Use the new@Querybuiltin as the entire RHS of a$var =assignment:$products = @Query(fetch_products, category: "shoes"). The slot isnulluntil the tool resolves; re-fire with@Run($products). The parser rejects the old form with a migrationParseException. TheQueryCallAST class andEvalContext.queryResultsare removed.QueryDeclnow carriestoolName+namedArgs(the legacyList<Argument> argsfield is gone). The@Runaction step accepts aStateReffirst arg so@Run($var)re-fires the bound query. - BREAKING:
@Eachnow takes three args —@Each(list, "name", template). The loop variable is named explicitly via a string literal and bound under its bare key inside the template (e.g.@Each(items, "row", Card(title: row.name))).$indexis still bound. The 2-arg implicit-$itemform is removed.@Mapand@Filterare unchanged.parseProgramrecords aParseExceptionfor shape-invalid@Eachcalls (wrong arity, non-string-literal name, reserved name, empty name, leading$).
Phase 1 — openui_core language and runtime #
The language core ships in 13 milestones built on top of the Phase 0
walking-skeleton lexer. All public symbols carry @experimental per
Decision D12.
- feat: walking-skeleton lexer covering the OpenUI Lang token set
(identifier, type, statevar, builtin sigil, string, number,
operator, punct, newline, EOF). Recoverable mode tolerates partial
tail tokens; eager mode throws
LexException. - feat: OpenUI Lang Pratt parser. Sealed
AstNodehierarchy (Literal,NullLiteral,Reference,StateRef,StateAssign,ArrayLit,ObjectLit,BinaryOp,UnaryOp,Ternary,MemberAccess,IndexAccess,CompCall,BuiltinCall,QueryCall,MutationCall);Statement+StatementKind+classifyStatement;parseProgram(source, {recoverable}),parseExpression(source),autoClose(text). - feat: streaming parser.
createStreamingParser({rootName})returns aStreamParserwithpush(chunk)/set(fullText); splits buffer at last bracket-depth-zero newline, runsautoCloseon the pending tail, re-parses in recoverable mode. ReturnsParseResultwithstatements, materializedroot, andParseMeta(incomplete,unresolved,orphaned,errors,stateDecls,queries,mutations). - feat: materializer.
materialize(rootName, statements, {incomplete})does graph-shaped reachability — BFS over the statement-id map, partitions into reachable / unresolved / orphaned. State, query, and mutation declarations are excluded from orphan analysis. LightweightElementNodecarries the unevaluated root RHS pluspartialflag. - feat: reactive
Store. Pure-Dart key/value bag with shallow equality short-circuit onset, listener subscribe/unsubscribe, unmodifiablegetSnapshot(), andinitialize(defaults, [persisted])that never overwrites user-modified bindings. Per Decision D4, oneStoreperRenderer. - feat: sealed
OpenUIErrorhierarchy.ParseError,EvaluationError,CyclicStateError,UnknownComponentError,McpToolError,ToolNotFoundError,AdapterMismatchError. Each carries a stable machine-readablecode, optionalmessage/hint/statementId, and structural equality so dedup overRenderer.onErrorlists reduces tolistEquals. - feat: AST evaluator.
evaluate(AstNode, EvalContext) → Object?walks every concrete AST case (literals, references with cycle detection, state refs / assigns, array / object literals, binary and unary operators, ternary, member access, index access).BuiltinCalldispatches throughEvalContext.builtins; comp, query, and mutation calls in expression position are category errors.withIteration(...)produces a child context that shares errors and cycle state. - feat: functional builtins.
functionalBuiltinsregistry drops@Count,@Filter,@Each,@Mapstraight intoEvalContext.builtins.$itemand$indexare pushed throughwithIterationper element; predicates and templates can be inline expressions orReferences. - feat: action steps and dispatcher. Sealed
ActionStepvariants (SetStep,ResetStep,RunStep,ContinueConversationStep,OpenUrlStep),ActionPlanwrapper,actionPlanFromAst(AstNode)bridge, anddispatchAction(...)that re-evaluatesvalueAstat click time per Decision D3.RunStepfailures halt the rest of the plan. - breaking (experimental):
actionPlanFromAstaccepts only a non-empty array literal whose elements are all valid@Set/@Reset/@Run/@ToAssistantcalls (strict: no bare builtins, noAction(...)wrapper, no empty[], no mixed non-action elements). Other shapes yieldnull. - feat:
mergeStatements(existing, patch, {rootId})for the LLM "edit, don't rewrite" pathway. Strips Markdown fences, applies upserts andNullLiteraldeletes, runs the materializer's orphan GC to drop unreachable value statements, re-emits with per-statement whitespace preserved. - feat:
ToolProviderinterface,ToolResultenvelope, andextractToolResulthelper. Mirrors spike S0.3 —isErrorthrowsMcpToolError, structured content wins over text, JSON-shaped text is decoded, otherwise the raw string. Nomcp_dartdependency in core. - feat:
Library<W>registry,Component<W>,defineComponent<W>(...),reactive(Schema)wrapper, and theReactiveAssignmarker +isReactiveAssignhelper.Schemais re-exported fromjson_schema_builder; thex-reactiveextension keyword survivestoJson()per spike S0.1. - feat:
evaluateElementProps(call, schema, context)— walks aCompCall's named args, emitsReactiveAssignmarkers for reactive props bound to a bare$stateref, evaluates the rest normally. Bridges the parser-side AST to the renderer-side prop contract. - feat:
parse(source, paramMap, {rootName})integration entry. Builds a fully-resolvedResolvedElementtree in one pass: ref resolution with cycle detection, positional → named prop mapping, required-prop validation (missing-required/null-required),excess-argsdetection,UnknownComponentErrorfor components not in theParamMap, array null-dropping for invalid children, orphan tracking, and$stateauto-declaration. Ports the JS reference'sparser.test.tscontract suite verbatim.