Releases: MesTTo/Meta-TypeScript-Talk
Release list
MeTTa TS 1.1.0
MeTTa TS 1.1.0
A pure-TypeScript implementation of MeTTa (Meta Type Talk), the OpenCog Hyperon language. It runs anywhere TypeScript runs: the browser, Node, Deno, Bun, and edge or serverless functions. No native addons, no WASM, no Rust.
Tested on Linux
This release is tested on Linux (Node 20, the CI matrix): lint, format, typecheck, the full test suite, and the build all run there. Because the engine is pure TypeScript with no native addon and no WASM, it is meant to be cross-platform and should run unchanged on any JavaScript runtime. Other operating systems are not yet part of the tested matrix.
What's new: Python interop
This release adds @metta-ts/py, an optional package that lets a MeTTa program call into Python. It carries two surfaces over one bridge: PeTTa's py-call and Hyperon's py-atom family.
py-call dispatches on the head of its argument, the way PeTTa does. A bare name is a builtin, a dotted name is a module function, and a leading-dot name is a method on a live object. py-eval runs a Python expression string and py-str folds a MeTTa list into a Python string:
!(py-call (math.gcd 12 18)) ; 6
!(py-eval "2 ** 10") ; 1024The py-atom family is Hyperon's surface over the same bridge. py-atom resolves a dotted path into an atom you can apply or read as a value, and py-dot, py-list, py-tuple, py-dict, and py-chain round it out:
!((py-atom operator.add) 40 2) ; 42
!(py-atom math.pi) ; 3.141592653589793Python runs in a separate CPython process and MeTTa talks to it over IPC, so the interpreter stays pure TypeScript and as fast as before. The package ships no Python dependency of its own: you pass in a bridge, the way MeTTaGrapher takes a GIF encoder. The reference bridge wraps pythonia. Because a call crosses a process boundary the ops are asynchronous, so you run with runAsync, or from the command line with metta-ts --py program.metta.
Value conversions follow PeTTa and its janus bridge: numbers both ways, a Python string to a Symbol, True/False/None to (@ true)/(@ false)/(@ none), a list to an expression, and anything else to a live handle. A raised Python error becomes an (Error <expr> <message>) atom carrying the real Python message, and evaluation continues, where PeTTa aborts. Enabling this grants the program the host's Python, so it is opt-in and meant for trusted source only.
Two differential oracles pin the behaviour. A byte-parity suite runs the same corpus through a live PeTTa checkout and through this package, comparing the result lines exactly. A second suite runs the py-atom surface through pip hyperon, comparing results on the numeric surface where the two marshallings coincide. Both are gated behind environment flags so the default suite needs no Python.
The one change to the engine is that a grounded atom's executor may now return a Promise, which is what lets an applied py-atom run asynchronously. Nothing returned a Promise from that path before, so the synchronous behaviour is unchanged: the 270-assertion Hyperon oracle is byte-identical and the corpus microbench is within noise of 1.0.9.
Corpus benchmark
The engine is unchanged for pure-MeTTa programs, so the PeTTa-corpus benchmark (107 shared programs, 97 both engines pass, median 2.01x, geomean 2.06x) is identical to 1.0.9. See packages/node/bench/RESULTS-corpus.md for the full per-program table.
Major performance gains (since 1.0.0)
The speed comes from general engine work:
- an O(1)-stack reduce-loop trampoline and worklist, so deep recursion does not grow the JS stack;
- deferred rule-RHS freshening with a head-shape candidate pre-filter;
- Prolog-style clause indexing by head functor and by every ground-leaf argument, so a keyed query over a 1,000,000-atom space resolves in about 0.2 to 1.4 ms;
- ground-atom type memoisation and an exact-match ground-fact index;
- automatic tabling of pure functions, including ones defined at runtime, and moded (variant) tabling for non-ground pure calls;
- a native-code compiler for the pure deterministic int/bool/tuple subset, with tail-recursion compiled to loops and higher-order specialisation;
- worker-thread parallelism:
(once (hyperpose ...))races branches across CPU cores on Node, and aSharedArrayBufferflat matcher scans large knowledge bases in parallel; - the compiled clause-skeleton and JavaScript-codegen search for match-free nondeterministic groups.
Every optimisation is verified byte-identical against the 270-assertion Hyperon oracle.
What is in this release
@metta-ts/coreis the interpreter, parser, type system, pattern matching, standard library, and static analyzer, as a single ESM bundle. It passes all 270 assertions of Hyperon's oracle corpus, cross-checked against LeaTTa, the machine-checked (Lean 4) MeTTa semantics pinned to the same commit.@metta-ts/hyperonis a TypeScript class API modeled on Python'shyperon, with a JavaScript interop layer (js-atom,js-dot,js-list,js-dict) that calls into the host runtime directly.@metta-ts/edslis a typed eDSL with term builders, special-form combinators, and a tagged-template surface.@metta-ts/pyis the new Python interop package, described above:py-calland thepy-atomfamily over a caller-supplied pythonia bridge, opt-in and asynchronous.@metta-ts/nodehas themetta-tsCLI, with--checkfor static analysis and--pyfor Python interop, plus fileimport!and the worker-thread parallel matcher.@metta-ts/browseris a browser entry with an in-memory virtual file system forimport!.@metta-ts/grapherrenders a MeTTa reduction as a node graph or a nested-block view, as static SVGs or an animated GIF, with a data-driven stylesheet for node size and colour.@metta-ts/das-clientand@metta-ts/das-gatewayare an optional client to SingularityNET's Distributed AtomSpace, run end to end against a live cluster, with atom handles matching the AtomDB byte for byte.
Install
npm install @metta-ts/core # the interpreter (works in any JS runtime)
npm install -g @metta-ts/node # the metta-ts CLI
npm install @metta-ts/py pythonia # optional: call Python from MeTTaRun a Python-using program from the command line:
metta-ts --py program.metta # needs pythonia installed and python3 on PATHProvenance
- Semantics: hyperon-experimental, pinned to commit
3f76dc4. - Python interop surface: PeTTa's
py-calland Hyperon'spy-atomfamily, over pythonia. - Verified spec and differential oracle: LeaTTa (Lean 4).
- Formal models: Alloy specs in
spec/for the matcher's deep loop rejection and the compiled search's occurs check. - License: MIT.
MeTTa TS 1.0.9
MeTTa TS 1.0.9
A pure-TypeScript implementation of MeTTa (Meta Type Talk), the OpenCog Hyperon language. It runs anywhere TypeScript runs: the browser, Node, Deno, Bun, and edge or serverless functions. No native addons, no WASM, no Rust.
Tested on Linux
This release is tested on Linux (Node 20, the CI matrix): lint, format, typecheck, the full test suite, and the build all run there. Because the engine is pure TypeScript with no native addon and no WASM, it is meant to be cross-platform and should run unchanged on any JavaScript runtime. Other operating systems are not yet part of the tested matrix.
What's new: a recovering CST for editors and language servers
1.0.8 added a span-tracking parse for the static analyzer. This release turns it into a concrete syntax tree an editor can build on. parseCst never throws, so a language server can keep offering features while a document is mid-edit: an unclosed ( closes at end of input, an unexpected ) and an unterminated string each become a diagnostic instead of an exception, and deep nesting is bounded without a recursive overflow. The tree also carries what an editor needs and the analyzer did not: the comments, a syntactic kind per node, the paren spans, and the span of a top-level ! query.
Leaf atoms still come from the interpreter's own reader primitives, so on valid input the CST is byte-identical to parseAll. A 1000-run differential checks the atoms and bang flags against the plain reader, and a 2000-run fuzz checks that the parser never throws on arbitrary input. The diagnostics are shaped as Language Server Protocol Diagnostics with a range, a severity, and a stable code, so an editor consumes them directly. The static analyzer and metta-ts --check from 1.0.8 are unchanged and still read the interpreter's own signature table:
error[arity-mismatch]: prog.metta:1:2
|
1 | !(car-atom 1 2)
| ^^^^^^^^^^^^^^ car-atom expects 1 argument, got 2
None of this touches the evaluator. parseCst is off the runFile hot path; the only change to shared code is that readStringAt now reports whether a string was terminated instead of throwing, and the plain parser re-throws exactly as before. The 270-assertion Hyperon oracle and every byte-identical experimental suite still pass, and a parse/eval microbench is within noise of 1.0.8.
Corpus benchmark
The engine is unchanged in this release, so the PeTTa-corpus benchmark (107 shared programs, 97 both engines pass, median 2.01x, geomean 2.06x) is identical to 1.0.7. See packages/node/bench/RESULTS-corpus.md for the full per-program table.
Major performance gains (since 1.0.0)
The speed comes from general engine work:
- an O(1)-stack reduce-loop trampoline and worklist, so deep recursion does not grow the JS stack;
- deferred rule-RHS freshening with a head-shape candidate pre-filter;
- Prolog-style clause indexing by head functor and by every ground-leaf argument, so a keyed query over a 1,000,000-atom space resolves in about 0.2 to 1.4 ms;
- ground-atom type memoisation and an exact-match ground-fact index;
- automatic tabling of pure functions, including ones defined at runtime, and moded (variant) tabling for non-ground pure calls;
- a native-code compiler for the pure deterministic int/bool/tuple subset, with tail-recursion compiled to loops and higher-order specialisation;
- worker-thread parallelism:
(once (hyperpose ...))races branches across CPU cores on Node, and aSharedArrayBufferflat matcher scans large knowledge bases in parallel; - the compiled clause-skeleton and JavaScript-codegen search for match-free nondeterministic groups, added in 1.0.7.
Every optimisation is verified byte-identical against the 270-assertion Hyperon oracle.
What is in this release
@metta-ts/coreis the interpreter, parser, type system, pattern matching, and standard library, as a single ESM bundle. It now also carries the static analyzer and its diagnostic model, described above. It passes all 270 assertions of Hyperon's oracle corpus (the full dependent-type tier, spaces and mutable state, nondeterminism, grounded operations, and documentation), cross-checked against LeaTTa, the machine-checked (Lean 4) MeTTa semantics pinned to the same commit.@metta-ts/hyperonis a TypeScript class API modeled on Python'shyperon, with a JavaScript interop layer (js-atom,js-dot,js-list,js-dict) that calls into the host runtime directly.@metta-ts/edslis a typed eDSL with term builders, special-form combinators, and a tagged-template surface.@metta-ts/nodehas themetta-tsCLI, now with--checkfor static analysis, plus fileimport!and the worker-thread parallel matcher.@metta-ts/browseris a browser entry with an in-memory virtual file system forimport!.@metta-ts/grapherrenders a MeTTa reduction as a node graph or a nested-block view, as static SVGs or an animated GIF, with a data-driven stylesheet for node size and colour.@metta-ts/das-clientand@metta-ts/das-gatewayare an optional client to SingularityNET's Distributed AtomSpace, run end to end against a live cluster, with atom handles matching the AtomDB byte for byte.
Install
npm install @metta-ts/core # the interpreter (works in any JS runtime)
npm install -g @metta-ts/node # the metta-ts CLICheck a file without running it:
metta-ts --check program.metta # arity errors, rustc-style
metta-ts --check --undefined-symbols program.metta # also "did you mean" on unknown heads
metta-ts --check --json program.metta # diagnostics as an LSP Diagnostic[]Provenance
- Semantics: hyperon-experimental, pinned to commit
3f76dc4. - Verified spec and differential oracle: LeaTTa (Lean 4).
- Formal models: Alloy specs in
spec/for the matcher's deep loop rejection and the compiled search's occurs check. - License: MIT.
MeTTa TS 1.0.8
MeTTa TS 1.0.8
A pure-TypeScript implementation of MeTTa (Meta Type Talk), the OpenCog Hyperon language. It runs anywhere TypeScript runs: the browser, Node, Deno, Bun, and edge or serverless functions. No native addons, no WASM, no Rust.
Tested on Linux
This release is tested on Linux (Node 20, the CI matrix): lint, format, typecheck, the full test suite, and the build all run there. Because the engine is pure TypeScript with no native addon and no WASM, it is meant to be cross-platform and should run unchanged on any JavaScript runtime. Other operating systems are not yet part of the tested matrix.
What's new: a static analyzer and metta-ts --check
This release adds a static analyzer that catches mistakes before a program runs and reports them the way a modern compiler does: the exact source span underlined, an error code, a message, and a suggested fix. It ships in @metta-ts/core as a library and on the metta-ts CLI as --check.
The analyzer reads the interpreter's own signature table, so it flags exactly the calls the interpreter itself would reject. A builtin called with the wrong number of arguments is checked against the same (-> ...) declaration the evaluator uses at run time, not against a second copy of the arity rules that could drift from it:
error[arity-mismatch]: prog.metta:1:2
|
1 | !(car-atom 1 2)
| ^^^^^^^^^^^^^^ car-atom expects 1 argument, got 2
An opt-in --undefined-symbols pass adds a "did you mean" on an unknown head, suggesting the closest defined name by edit distance. It is off by default because MeTTa's add-mode makes an unknown head legal: (foo 1 2) with no rule for foo is data added to the space, not a typo. With the flag on, (fibonaci 10) next to a defined fibonacci becomes a warning that carries the fix, never an error.
Precise spans come from a span-tracking parse that reuses the interpreter's own reader primitives, so the analyzer cannot disagree with the real parser about where a token starts or ends. --json emits the findings as a Language Server Protocol Diagnostic[], each with a range, a severity, a code, and suggestions that carry an applicability tier, so an editor or a language server can consume them directly.
None of this changes the evaluator. The only edit to existing run-time code is a refactor of the parser that exports the primitives the span parser reuses, and it is guarded by the parser's own tests. So the 270-assertion Hyperon oracle and the corpus benchmark below are byte-identical to 1.0.7, and the analyzer adds no dependency.
Corpus benchmark
The engine is unchanged in this release, so the PeTTa-corpus benchmark (107 shared programs, 97 both engines pass, median 2.01x, geomean 2.06x) is identical to 1.0.7. See packages/node/bench/RESULTS-corpus.md for the full per-program table.
Major performance gains (since 1.0.0)
The speed comes from general engine work:
- an O(1)-stack reduce-loop trampoline and worklist, so deep recursion does not grow the JS stack;
- deferred rule-RHS freshening with a head-shape candidate pre-filter;
- Prolog-style clause indexing by head functor and by every ground-leaf argument, so a keyed query over a 1,000,000-atom space resolves in about 0.2 to 1.4 ms;
- ground-atom type memoisation and an exact-match ground-fact index;
- automatic tabling of pure functions, including ones defined at runtime, and moded (variant) tabling for non-ground pure calls;
- a native-code compiler for the pure deterministic int/bool/tuple subset, with tail-recursion compiled to loops and higher-order specialisation;
- worker-thread parallelism:
(once (hyperpose ...))races branches across CPU cores on Node, and aSharedArrayBufferflat matcher scans large knowledge bases in parallel; - the compiled clause-skeleton and JavaScript-codegen search for match-free nondeterministic groups, added in 1.0.7.
Every optimisation is verified byte-identical against the 270-assertion Hyperon oracle.
What is in this release
@metta-ts/coreis the interpreter, parser, type system, pattern matching, and standard library, as a single ESM bundle. It now also carries the static analyzer and its diagnostic model, described above. It passes all 270 assertions of Hyperon's oracle corpus (the full dependent-type tier, spaces and mutable state, nondeterminism, grounded operations, and documentation), cross-checked against LeaTTa, the machine-checked (Lean 4) MeTTa semantics pinned to the same commit.@metta-ts/hyperonis a TypeScript class API modeled on Python'shyperon, with a JavaScript interop layer (js-atom,js-dot,js-list,js-dict) that calls into the host runtime directly.@metta-ts/edslis a typed eDSL with term builders, special-form combinators, and a tagged-template surface.@metta-ts/nodehas themetta-tsCLI, now with--checkfor static analysis, plus fileimport!and the worker-thread parallel matcher.@metta-ts/browseris a browser entry with an in-memory virtual file system forimport!.@metta-ts/grapherrenders a MeTTa reduction as a node graph or a nested-block view, as static SVGs or an animated GIF, with a data-driven stylesheet for node size and colour.@metta-ts/das-clientand@metta-ts/das-gatewayare an optional client to SingularityNET's Distributed AtomSpace, run end to end against a live cluster, with atom handles matching the AtomDB byte for byte.
Install
npm install @metta-ts/core # the interpreter (works in any JS runtime)
npm install -g @metta-ts/node # the metta-ts CLICheck a file without running it:
metta-ts --check program.metta # arity errors, rustc-style
metta-ts --check --undefined-symbols program.metta # also "did you mean" on unknown heads
metta-ts --check --json program.metta # diagnostics as an LSP Diagnostic[]Provenance
- Semantics: hyperon-experimental, pinned to commit
3f76dc4. - Verified spec and differential oracle: LeaTTa (Lean 4).
- Formal models: Alloy specs in
spec/for the matcher's deep loop rejection and the compiled search's occurs check. - License: MIT.
MeTTa TS 1.0.7
MeTTa TS 1.0.7
A pure-TypeScript implementation of MeTTa (Meta Type Talk), the OpenCog Hyperon language. It runs anywhere TypeScript runs: the browser, Node, Deno, Bun, and edge or serverless functions. No native addons, no WASM, no Rust.
Tested on Linux
This release is tested on Linux (Node 20, the CI matrix): lint, format, typecheck, the full test suite, and the build all run there. Because the engine is pure TypeScript with no native addon and no WASM, it is meant to be cross-platform and should run unchanged on any JavaScript runtime. Other operating systems are not yet part of the tested matrix.
What's new: the proof-size-bounded backward chainer, from losing to winning
Nil Geisweiller's bfc-xp benchmark searches a Łukasiewicz propositional calculus for a proof of a target formula under a fixed size bound, backtracking through modus ponens and three axiom schemes. It is a real nondeterministic search, not a lookup, and it was the one place PeTTa still beat MeTTa TS. This release closes that gap by compiling the search itself, not just the terms it searches over.
A match-free nondeterministic group (no clause queries a space, only recursion, if-guards, and integer arithmetic) now compiles in two steps. First, every clause becomes a skeleton: a tree of constant subtrees, clause-variable slots, and structured nodes, computed once per group rather than copied per call. Second, the skeleton compiles to specialized JavaScript, one function per functor, generated once via new Function and shared by every run: head unification becomes read/write-mode code that fails at the first mismatch with no allocation, and body arguments and templates become direct constructor expressions with integer arithmetic unboxed. Underneath both steps, search variables are cell variables: a binding lives in a mutable slot on the variable itself, so dereferencing is pointer-chasing and undoing a failed branch is popping a trail array, no string-keyed map anywhere. Every bind carries an occurs check, so a would-be cyclic binding fails the search instead of looping, exactly the discipline hasLoop enforces on the interpreter's own immutable bindings and SWI-Prolog enforces under occurs_check(true). A model in spec/loop_reject.als proves the two mechanisms reject exactly the same binding sets, in every possible bind order. An environment that forbids dynamic code (a CSP without unsafe-eval) falls back to running the skeleton directly, still far faster than the plain interpreter; a group that does query a space (like nilbc, MeTTa TS's dependently-typed backward chainer) is unaffected and keeps running on the original interpreter-backed search.
The result, measured with hyperfine (mean ± σ, wall clock, engine startup included, each row from one hyperfine invocation so the two columns are directly comparable):
| benchmark | MeTTa TS | PeTTa |
|---|---|---|
jarr (size 13) |
124.8 ms ± 4.2 ms | 182.9 ms ± 10.6 ms |
pm2.27 (size 13) |
121.6 ms ± 1.3 ms | 183.0 ms ± 8.3 ms |
imim1 (size 15) |
152.2 ms ± 4.1 ms | 212.3 ms ± 3.9 ms |
jarr (size 17), PeTTa with occurs_check(true) |
455.5 ms ± 69.5 ms | 476.0 ms ± 11.8 ms |
loowoz (size 19), PeTTa with occurs_check(true) |
2.092 s ± 0.063 s | 2.501 s ± 0.003 s |
The last two rows run PeTTa with occurs_check(true), which its SWI-Prolog translation does not set (the flag defaults to off). At these two deeper searches that gap is not just a speed difference: PeTTa as shipped finds 94 answers for jarr at size 17 where only 91 exist, and 44 for loowoz at size 19 where only 3 exist, the surplus being cyclic-binding artifacts that occurs_check is exactly the guard against (the same requirement bfc-xp's own SWI harness documents). Run correctly, PeTTa is a little slower here too. Every MeTTa TS answer above is checked byte-identical to the plain interpreter by a differential oracle that runs the search both ways (packages/core/src/moded-tabling.test.ts), and the compiled and interpreted engines' outputs are additionally diffed directly at sizes 17 and 19.
Corpus benchmark
The existing PeTTa-corpus benchmark (107 shared programs, 97 both engines pass, median 2.01x, geomean 2.06x) is unaffected by this release: none of those programs exercise a match-free nondeterministic group, so they run the same code as before. See packages/node/bench/RESULTS-corpus.md for the full per-program table.
Major performance gains (since 1.0.0)
The speed comes from general engine work:
- an O(1)-stack reduce-loop trampoline and worklist, so deep recursion does not grow the JS stack;
- deferred rule-RHS freshening with a head-shape candidate pre-filter;
- Prolog-style clause indexing by head functor and by every ground-leaf argument, so a keyed query over a 1,000,000-atom space resolves in about 0.2 to 1.4 ms;
- ground-atom type memoisation and an exact-match ground-fact index;
- automatic tabling of pure functions, including ones defined at runtime, and moded (variant) tabling for non-ground pure calls;
- a native-code compiler for the pure deterministic int/bool/tuple subset, with tail-recursion compiled to loops and higher-order specialisation;
- worker-thread parallelism:
(once (hyperpose ...))races branches across CPU cores on Node, and aSharedArrayBufferflat matcher scans large knowledge bases in parallel; - the compiled clause-skeleton and JavaScript-codegen search described above, for match-free nondeterministic groups.
Every optimisation is verified byte-identical against the 270-assertion Hyperon oracle.
What is in this release
@metta-ts/coreis the interpreter, parser, type system, pattern matching, and standard library, as a single ESM bundle. It passes all 270 assertions of Hyperon's oracle corpus (the full dependent-type tier, spaces and mutable state, nondeterminism, grounded operations, and documentation), cross-checked against LeaTTa, the machine-checked (Lean 4) MeTTa semantics pinned to the same commit.@metta-ts/hyperonis a TypeScript class API modeled on Python'shyperon, with a JavaScript interop layer (js-atom,js-dot,js-list,js-dict) that calls into the host runtime directly.@metta-ts/edslis a typed eDSL with term builders, special-form combinators, and a tagged-template surface.@metta-ts/nodehas themetta-tsCLI, fileimport!, and the worker-thread parallel matcher.@metta-ts/browseris a browser entry with an in-memory virtual file system forimport!.@metta-ts/grapherrenders a MeTTa reduction as a node graph or a nested-block view, as static SVGs or an animated GIF, with a data-driven stylesheet for node size and colour.@metta-ts/das-clientand@metta-ts/das-gatewayare an optional client to SingularityNET's Distributed AtomSpace, run end to end against a live cluster, with atom handles matching the AtomDB byte for byte.
Install
npm install @metta-ts/core # the interpreter (works in any JS runtime)
npm install -g @metta-ts/node # the metta-ts CLIProvenance
- Semantics: hyperon-experimental, pinned to commit
3f76dc4. - Verified spec and differential oracle: LeaTTa (Lean 4).
- Formal models: Alloy specs in
spec/for the matcher's deep loop rejection and the compiled search's occurs check. - License: MIT.
MeTTa TS 1.0.6
This release adds @metta-ts/grapher, a visual, structural editor for MeTTa that runs entirely in the browser.
@metta-ts/grapher
MeTTaGrapher draws a program two ways and runs it on the same interpreter as the rest of the packages: a node graph of connected boxes, and nested blocks where a form contains its arguments. Both are the same MeTTa atom, so anything that produces atoms feeds it, including the eDSL.
It is a structural editor: you never type into a free-form text box, you select a term and act on it, so the program is always a valid tree. In the blocks view the arrow keys walk the cursor through the tree, typing on a leaf re-parses it back into an atom, and the source panel stays in step. In the graph view you add nodes and drag a node's top port onto another to connect it as a child, drag it onto empty space to detach, and delete with the keyboard. An illegal edge (a self-loop, a duplicate, or a cycle) is rejected, with the connect line green over a node it can legally join and red over one it cannot.
Watch a query reduce. Press Play and the tree folds up to its answer one real reduction at a time, morphing from each state into the next. When a rule fires you see the substitution: the rule body appears with its variables as hollow slots that fill in with the values they matched, read from the engine so a literal in the rule is never mistaken for a variable. A soft glow marks the subterm reducing, an operation morphs into its result, a step's consumed pieces coalesce into the result the way droplets merge, and a nondeterministic step fans out to show every branch. The playthrough matches the interpreter: case and let* keep their structural arguments unevaluated so a case-based recursion terminates, and where a single step cannot advance a query the trace reconciles its endpoint with full evaluation, so Play ends where Run does.
Export a GIF of the reduction: the block view, the node graph, or both side by side. The frame math is pure, so a reduction GIF can be produced from the command line as well as the browser.
Drive the picture from MeTTa through an isolated &grapher space: (color T C), (highlight T), (focus T), (label T text), and (background C), reachable from MeTTa, TypeScript, or the eDSL.
Every runnable example on the docs site now has a Visualize button that opens it in the editor. There is a hands-on walkthrough at https://mestto.github.io/Meta-TypeScript-Talk/tools/grapher.
Install
npm install @metta-ts/grapherAll eight @metta-ts/* packages are published at 1.0.6 with npm provenance. The 270-assertion Hyperon oracle corpus stays byte-identical.
MeTTa TS 1.0.5: ergonomic typed eDSL
An ergonomics release for the typed TypeScript eDSL, @metta-ts/edsl. The engine is unchanged and stays faster than PeTTa on all 97 shared corpus programs; this release is about writing MeTTa from TypeScript with far less ceremony and much stronger types.
eDSL redesign
The old surface (S, v("x"), rel("name"), iff/matchSelf) is replaced. No name is written twice anymore.
- Proxy-minted names and variables.
const { Likes, fact, Ada } = names()andconst { x, thing } = vars(). A bare name grounds to its symbol; a called name applies it, soLikes(Ada, thing)builds(Likes Ada thing). The JS binding is the name. - Capitalized special forms:
If,Case,Let,LetStar,Match,Superpose,Collapse,Empty,Unify,Sealed,Quote, with the grounded ops staying lowercase. - A two-way host bridge.
db.fn/db.fns/db.asyncFnregister plain typed TypeScript functions with arguments auto-unwrapped and the result auto-grounded.db.call.fact(5)anddb.import("fact")call MeTTa functions back from TypeScript.
New in this release
- Optional typed schema.
mettaDB<{ fact: (n: number) => number }>()typescall,import, andfnfrom a declared schema, sodb.call.fact(5)isnumber[],db.import("fact")is(n: number) => number | undefined, anddb.fnis checked against the signature. With no schema the surface stays permissive. - Typed source queries.
db.q("(Likes Ada $thing)")returns rows typed by the pattern's variables,{ thing: unknown }[], with the keys extracted at compile time. A key that is not a variable in the source is a compile error. It types the variable structure, not the values, which come from runtime rewriting. - JSON and dict-spaces.
db.useJson()enables the module, andjsonEncode/jsonDecode/dictSpace/getKeys/getValuebridge JSON and MeTTa spaces, so a decoded JSON object becomes a queryable space.
The m tagged template and raw run surfaces remain, and every builder still produces an ordinary atom that runs on the same faithful engine, verified against the 270-assertion Hyperon oracle and the LeaTTa Lean spec.
Packages
Published to npm with provenance: @metta-ts/core, @metta-ts/node, @metta-ts/browser, @metta-ts/hyperon, @metta-ts/das-client, @metta-ts/das-gateway, @metta-ts/edsl.
MeTTa TS 1.0.4: faster than PeTTa on all 97
The parity release: MeTTa TS is now faster than PeTTa on all 97 shared corpus programs, median about 2×, from pure TypeScript. Verified against the 270-assertion Hyperon oracle and the LeaTTa Lean spec throughout.
Highlights
- Compiled nondeterministic search. A multi-equation function whose clause bodies chain space matches and recursive calls (the backward-chainer class) compiles to a clause-major depth-first collect-all search, the same fragment PeTTa hands to Prolog's clause alternatives. Head unification, solution destructuring, and space matching reuse the interpreter's own primitives, so semantics are inherited rather than reimplemented.
nilbcgoes from 2.2 s to 0.40 s, under PeTTa's 0.71 s. - Compiled add-atom saturation loops. The add-if-absent idiom compiles to one exact-membership probe plus append, and a single-branch
caseover a space match becomes a snapshot-and-thread loop with Empty-pruned branches.peano, the last trailing benchmark, goes from 2.7 s to 0.22 s, 7.7× under PeTTa's 1.69 s, byte-identical. - Identity-preserving evaluation. The reduce loop returns the input expression when every evaluated argument is unchanged instead of rebuilding an equal copy, which keeps the evaluated-mark and type caches hitting for any store that re-materialises canonical terms.
- Flat atomspace, fixed. The opt-in compact store's regressions are gone: a decode cache and an open-addressing intern table put
peanounder the flag at parity and cutmatespacefastto 1.6× the default's time at 3× less peak memory. It stays opt-in as a memory mode.
One documented nuance: the nondeterministic compiler's fresh variables are alpha-equivalent to the interpreter's rather than byte-equal (consistently renamed, deterministic run to run) — the equality the oracle and LeaTTa check. On the corpus exactly one printed line renames one variable.
Benchmark
On the PeTTa example corpus, Hyperon-faithful subset, both engines pass 97 shared programs and MeTTa TS is faster on every one: median 2.01×, geomean 2.06×, with peano 7.7×, fib 5.8×, tilepuzzle 3.9×, matespacefast 2.3×, nilbc 1.8×. matespace and matespace2 remain PeTTa-specific and excluded: run through hyperon-experimental itself they reduce to empty, so no Hyperon-faithful engine reproduces PeTTa's count. Full table in packages/node/bench/RESULTS-corpus.md.
Packages
Published to npm with provenance: @metta-ts/core, @metta-ts/node, @metta-ts/browser, @metta-ts/hyperon, @metta-ts/das-client, @metta-ts/das-gateway, @metta-ts/edsl.
MeTTa TS 1.0.3
A performance release, verified byte-identical against the 270-assertion Hyperon oracle and the LeaTTa Lean spec. This is a patch over 1.0.2 with the same engine work; it satisfies the lint and prettier CI gates that the 1.0.2 changeset tripped and refreshes the corpus benchmark on a quiet machine.
Highlights
- Conjunctive worst-case-optimal collapse-count. A
(length (collapse (match &self (, …) …)))folds the WCO join and counts each solution instead of materialising the answer set, sopermutationsnow beats PeTTa about 1.9×. - Compiled impure function bodies.
if,let,let*, grounded ops,add-atom, tuples, and recursion compile to a slot machine, with native recursion that propagates stack overflow identically to the interpreter. - Indexed named spaces. Named spaces get O(1) ground membership, so
tilepuzzlenow beats PeTTa about 3.9×. - Collapse-count routing, lazy AtomLog ground index, streamed
(case (match …) …)boundary, query-variable symbolic compilation, constructor short-circuit. - Experimental flat atomspace, opt-in.
Benchmark
On the PeTTa example corpus, Hyperon-faithful subset, MeTTa TS passes 97 shared programs and is faster than PeTTa on 95, median about 2×, from pure TypeScript. matespace and matespace2 are PeTTa-specific and excluded: run through hyperon-experimental itself they reduce to empty, so no Hyperon-faithful engine reproduces PeTTa's count.
Packages
Published to npm with provenance: @metta-ts/core, @metta-ts/node, @metta-ts/browser, @metta-ts/hyperon, @metta-ts/das-client, @metta-ts/das-gateway, @metta-ts/edsl.
MeTTa TS 1.0.2
A performance release. Every change is verified byte-identical against the 270-assertion Hyperon oracle and the LeaTTa Lean spec.
Highlights
- Conjunctive worst-case-optimal collapse-count. A
(length (collapse (match &self (, …) …)))folds the WCO join and counts each solution instead of materialising the answer set, sopermutationsnow beats PeTTa about 2.0×. - Compiled impure function bodies.
if,let,let*, grounded ops,add-atom, tuples, and recursion compile to a slot machine, with native recursion that propagates stack overflow identically to the interpreter. - Indexed named spaces. Named spaces get O(1) ground membership, so
tilepuzzlenow beats PeTTa about 4.1×. - Collapse-count routing. Count a build-then-match or an all-distinct-variable collapse without re-emitting the result set.
- Lazy AtomLog ground index, streamed
(case (match …) …)boundary, query-variable symbolic compilation, constructor short-circuit. - Experimental flat atomspace, opt-in.
Benchmark
On the PeTTa example corpus, Hyperon-faithful subset, MeTTa TS passes 97 shared programs and is faster than PeTTa on 95, median about 2×, from pure TypeScript. matespace and matespace2 are PeTTa-specific and excluded: run through hyperon-experimental itself they reduce to empty, so no Hyperon-faithful engine reproduces PeTTa's count.
Packages
Published to npm with provenance: @metta-ts/core, @metta-ts/node, @metta-ts/browser, @metta-ts/hyperon, @metta-ts/das-client, @metta-ts/das-gateway, @metta-ts/edsl.
MeTTa TS 1.0.1
Patch release over 1.0.0.
- Adds the
./package.jsonsubpath to each package'sexports, so tools that read it (require('@metta-ts/core/package.json')) resolve. - Published with npm provenance, so every package is cryptographically linked to this repo and commit (verified build via GitHub Actions).
No API or behavior changes from 1.0.0.