Deterministic
f(document, state) -> ComputedFrame. Given a document and state, the output is always identical. No side effects, no DOM, no framework.
wity-graph → documents as state machines. Declarative, headless, renderer-agnostic reactive knowledge. Stored as <wity-knowledge>.
A declarative reactive-knowledge layer for authoring interactive knowledge documents as state machines. Encode prose, LaTeX math, media, simulations, typed I/O ports, and reactive state in a single composable document, stored as <wity-knowledge>.
For AI coding agents: llms.txt · llms-full.txt · llms-api.txt
| Package | Purpose | Environment |
|---|---|---|
@wity-ai/rkf-core | Parse, evaluate, serialize, validate, expression evaluator, edit API | Browser + Node.js |
import * as graph from '@wity/graph-headless';
import { evaluate, initState, serialize, parse, setGraphProvider } from '@wity-ai/rkf-core';
// An RKF document is a plain object: the model parse() returns and serialize() takes.
const doc = {
version: '2.0', id: 'demo', title: 'Hello RKF',
vars: [{ tag: 'rkf-var', id: 'x', type: 'number', init: 0.5 }],
sections: [{
tag: 'rkf-section', id: 'intro',
children: [
{ tag: 'rkf-env', type: 'prose', content: 'Move the slider to change the value.' },
{
tag: 'rkf-machine', id: 'viz',
vars: [], gates: [], transforms: [], machines: [],
derives: [{ tag: 'rkf-derive', id: 'y', expr: 'x * x' }],
ports: [{ tag: 'rkf-port', dir: 'in', var: 'x', type: 'continuous', min: 0, max: 1, step: 0.01, label: 'x' }],
children: [{
tag: 'rkf-canvas', width: 400, height: 300,
children: [{ tag: 'rkf-circle', cx: 'x', cy: 'y', r: 8, fill: '#3b82f6' }],
}],
},
],
}],
};
const state = initState(doc); // { x: 0.5 }
const frame = evaluate(doc, state); // ComputedFrame
for (const mark of frame.marks) {
console.log(mark.tag, mark.cx, mark.cy, mark.r); // rkf-circle 0.5 0.25 8
}
// Stored form: a <wity-knowledge> graph. parse() / serialize() need graph-headless, injected once
// (in Node.js also setXmlParser(new DOMParser())).
setGraphProvider(graph);
const xml = serialize(doc); // <wity-knowledge version="1"> … </wity-knowledge>
const same = parse(xml); // the same documentAn RKF document models documents as state machines, grounded in three vector spaces:
f(document: RkfDocument, state: Object) -> ComputedFramedocument is the document model — from parse(), or built directly (immutable during evaluation)state is the current variable values (from initState() or after applyUpdates())ComputedFrame contains resolved marks, controls (dir="in" ports), envs, gates, outputs (dir="out" ports), and section structurerkf-var) -- dimensions of the machine's staterkf-gate) -- named boolean conditions over feature-spacerkf-transform) -- state transitions triggered by gatesState is emergent, not declared -- it arises from regions in feature-space recognised by gates.
No DOM. No framework. No side effects. Call evaluate(doc, state) at any point with any state.