nodality 1.2.9 → 1.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/mcp-server.mjs +86 -0
- package/bin/nodality.js +12 -0
- package/bin/schema-cli.mjs +72 -0
- package/dist/animator.cjs.js.LICENSE.txt +1 -1
- package/dist/animator.esm.js.LICENSE.txt +1 -1
- package/dist/audionew.cjs.js.LICENSE.txt +1 -1
- package/dist/audionew.esm.js.LICENSE.txt +1 -1
- package/dist/base.cjs.js.LICENSE.txt +1 -1
- package/dist/base.esm.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-desktop-bar.esm.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/beta-mobile-bar.esm.js.LICENSE.txt +1 -1
- package/dist/bundle.umd.js +1 -1
- package/dist/bundle.umd.js.LICENSE.txt +1 -28
- package/dist/button.cjs.js.LICENSE.txt +1 -1
- package/dist/button.esm.js.LICENSE.txt +1 -1
- package/dist/card-getter.cjs.js.LICENSE.txt +1 -1
- package/dist/card-getter.esm.js.LICENSE.txt +1 -1
- package/dist/center.cjs.js.LICENSE.txt +1 -1
- package/dist/center.esm.js.LICENSE.txt +1 -1
- package/dist/checkbox.cjs.js.LICENSE.txt +1 -1
- package/dist/checkbox.esm.js.LICENSE.txt +1 -1
- package/dist/code.cjs.js.LICENSE.txt +1 -1
- package/dist/code.esm.js.LICENSE.txt +1 -1
- package/dist/container.cjs.js.LICENSE.txt +1 -1
- package/dist/container.esm.js.LICENSE.txt +1 -1
- package/dist/data-list.cjs.js.LICENSE.txt +1 -1
- package/dist/data-list.esm.js.LICENSE.txt +1 -1
- package/dist/designer.cjs.js +1 -1
- package/dist/designer.cjs.js.LICENSE.txt +1 -28
- package/dist/designer.esm.js +1 -1
- package/dist/designer.esm.js.LICENSE.txt +1 -28
- package/dist/element-mapper.cjs.js +1 -1
- package/dist/element-mapper.cjs.js.LICENSE.txt +1 -1
- package/dist/element-mapper.esm.js +1 -1
- package/dist/element-mapper.esm.js.LICENSE.txt +1 -1
- package/dist/finalresult.esm.js +1 -1
- package/dist/finalresult.esm.js.LICENSE.txt +1 -28
- package/dist/flex-card.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-card.esm.js.LICENSE.txt +1 -1
- package/dist/flex-grid.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-grid.esm.js.LICENSE.txt +1 -1
- package/dist/flex-row.cjs.js.LICENSE.txt +1 -1
- package/dist/flex-row.esm.js.LICENSE.txt +1 -1
- package/dist/floating-input.cjs.js.LICENSE.txt +1 -1
- package/dist/floating-input.esm.js.LICENSE.txt +1 -1
- package/dist/free.cjs.js.LICENSE.txt +1 -1
- package/dist/free.esm.js.LICENSE.txt +1 -1
- package/dist/horizontal-scroller.cjs.js.LICENSE.txt +1 -1
- package/dist/horizontal-scroller.esm.js.LICENSE.txt +1 -1
- package/dist/image-picker.cjs.js.LICENSE.txt +1 -1
- package/dist/image-picker.esm.js.LICENSE.txt +1 -1
- package/dist/image.cjs.js.LICENSE.txt +1 -1
- package/dist/image.esm.js.LICENSE.txt +1 -1
- package/dist/index.cjs.js +1 -1
- package/dist/index.cjs.js.LICENSE.txt +1 -28
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.LICENSE.txt +1 -28
- package/dist/keyframe-animation.cjs.js.LICENSE.txt +1 -1
- package/dist/keyframe-animation.esm.js.LICENSE.txt +1 -1
- package/dist/link-getter.cjs.js.LICENSE.txt +1 -1
- package/dist/link-getter.esm.js.LICENSE.txt +1 -1
- package/dist/link.cjs.js.LICENSE.txt +1 -1
- package/dist/link.esm.js.LICENSE.txt +1 -1
- package/dist/meta-adder.cjs.js.LICENSE.txt +1 -1
- package/dist/meta-adder.esm.js.LICENSE.txt +1 -1
- package/dist/modal-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/modal-2025.esm.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.cjs.js.LICENSE.txt +1 -1
- package/dist/multiswitcher.esm.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/new-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/picker.cjs.js.LICENSE.txt +1 -1
- package/dist/picker.esm.js.LICENSE.txt +1 -1
- package/dist/progress.cjs.js.LICENSE.txt +1 -1
- package/dist/progress.esm.js.LICENSE.txt +1 -1
- package/dist/radio.cjs.js.LICENSE.txt +1 -1
- package/dist/radio.esm.js.LICENSE.txt +1 -1
- package/dist/range.cjs.js.LICENSE.txt +1 -1
- package/dist/range.esm.js.LICENSE.txt +1 -1
- package/dist/scroll-video.cjs.js.LICENSE.txt +1 -1
- package/dist/scroll-video.esm.js.LICENSE.txt +1 -1
- package/dist/side-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-bar.esm.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/side-nav-bar.esm.js.LICENSE.txt +1 -1
- package/dist/simple-bar.cjs.js.LICENSE.txt +1 -1
- package/dist/simple-bar.esm.js.LICENSE.txt +1 -1
- package/dist/slider-2025.cjs.js.LICENSE.txt +1 -1
- package/dist/slider-2025.esm.js.LICENSE.txt +1 -1
- package/dist/spacer.cjs.js.LICENSE.txt +1 -1
- package/dist/spacer.esm.js.LICENSE.txt +1 -1
- package/dist/stack.cjs.js.LICENSE.txt +1 -1
- package/dist/stack.esm.js.LICENSE.txt +1 -1
- package/dist/stacker.cjs.js.LICENSE.txt +1 -1
- package/dist/stacker.esm.js.LICENSE.txt +1 -1
- package/dist/table.cjs.js.LICENSE.txt +1 -1
- package/dist/table.esm.js.LICENSE.txt +1 -1
- package/dist/text-field.cjs.js.LICENSE.txt +1 -1
- package/dist/text-field.esm.js.LICENSE.txt +1 -1
- package/dist/text.cjs.js.LICENSE.txt +1 -1
- package/dist/text.esm.js.LICENSE.txt +1 -1
- package/dist/theme.cjs.js.LICENSE.txt +1 -1
- package/dist/theme.esm.js.LICENSE.txt +1 -1
- package/dist/transform-anim.cjs.js.LICENSE.txt +1 -1
- package/dist/transform-anim.esm.js.LICENSE.txt +1 -1
- package/dist/ulist.cjs.js.LICENSE.txt +1 -1
- package/dist/ulist.esm.js.LICENSE.txt +1 -1
- package/dist/video.cjs.js.LICENSE.txt +1 -1
- package/dist/video.esm.js.LICENSE.txt +1 -1
- package/dist/wrap.cjs.js.LICENSE.txt +1 -1
- package/dist/wrap.esm.js.LICENSE.txt +1 -1
- package/dist/zoom-card.cjs.js.LICENSE.txt +1 -1
- package/dist/zoom-card.esm.js.LICENSE.txt +1 -1
- package/layout/animator.js +1 -1
- package/layout/audio.js +1 -1
- package/layout/audionew.js +1 -1
- package/layout/base.js +1 -1
- package/layout/beta-desktop-bar.js +1 -1
- package/layout/beta-mobile-bar.js +1 -1
- package/layout/button.js +1 -1
- package/layout/center.js +1 -1
- package/layout/checkbox.js +1 -1
- package/layout/circle.js +1 -1
- package/layout/code.js +1 -1
- package/layout/container.js +1 -1
- package/layout/dropdown-2025.js +1 -1
- package/layout/flex-card.js +1 -1
- package/layout/flex-grid.js +1 -1
- package/layout/flex-row.js +1 -1
- package/layout/form-components/custom.js +1 -1
- package/layout/form-components/data-list.js +1 -1
- package/layout/form-components/floating-input.js +1 -1
- package/layout/form-components/form-all.js +1 -1
- package/layout/form-components/form.js +1 -1
- package/layout/form-components/image-picker.js +1 -1
- package/layout/form-components/picker.js +1 -1
- package/layout/form-components/radio.js +1 -1
- package/layout/form-components/radiogroup.js +1 -1
- package/layout/form-components/range.js +1 -1
- package/layout/free.js +1 -1
- package/layout/grid-switcher.js +1 -1
- package/layout/grid.js +1 -1
- package/layout/horizontal-scroller.js +1 -1
- package/layout/image.js +1 -1
- package/layout/index.js +1 -1
- package/layout/link.js +1 -1
- package/layout/list.js +1 -1
- package/layout/meta-adder.js +1 -1
- package/layout/modal-2025.js +1 -1
- package/layout/morph.js +1 -1
- package/layout/multiswitcher.js +1 -1
- package/layout/nav-bar.js +1 -1
- package/layout/nav-factor/custom-div.js +1 -1
- package/layout/new-nav-bar.js +1 -1
- package/layout/polygon.js +1 -1
- package/layout/prerender-site.js +1 -1
- package/layout/prerender.js +1 -1
- package/layout/progress.js +1 -1
- package/layout/row.js +1 -1
- package/layout/scroll-video.js +1 -1
- package/layout/side-bar.js +1 -1
- package/layout/side-nav-bar.js +1 -1
- package/layout/simple-bar.js +1 -1
- package/layout/slider-2025.js +1 -1
- package/layout/spacer.js +1 -1
- package/layout/stack.js +1 -1
- package/layout/svg.js +1 -1
- package/layout/switcher.js +1 -1
- package/layout/table.js +1 -1
- package/layout/text-field.js +1 -1
- package/layout/text.js +1 -1
- package/layout/ulist.js +1 -1
- package/layout/video.js +1 -1
- package/layout/wrap.js +1 -1
- package/layout/zoom-card.js +1 -1
- package/lib/agent-surface.js +1 -1
- package/lib/card-getter.js +1 -1
- package/lib/codegen.js +1 -1
- package/lib/data.js +1 -1
- package/lib/designer.js +21 -1
- package/lib/element-mapper.js +173 -16
- package/lib/element-params.generated.js +11 -0
- package/lib/keyframe-animation.js +1 -1
- package/lib/link-getter.js +1 -1
- package/lib/morph-node.js +1 -1
- package/lib/parse-html.js +151 -0
- package/lib/raster-inspect.js +1 -1
- package/lib/raster-ops.js +1 -1
- package/lib/raster-presets.js +1 -1
- package/lib/scroll-video.js +1 -1
- package/lib/seo.js +1 -1
- package/lib/stacker.js +1 -1
- package/lib/suggest.js +1 -1
- package/lib/theme.js +1 -1
- package/lib/transform-anim.js +1 -1
- package/lib/transition.js +1 -1
- package/lib/validate-nodes.js +112 -2
- package/lib/webmcp-adapter.js +1 -1
- package/package.json +5 -2
- package/schema.json +7953 -0
- package/scripts/generate-schema.mjs +251 -0
- package/skills/nodality/SKILL.md +71 -1
package/bin/mcp-server.mjs
CHANGED
|
@@ -135,6 +135,54 @@ const TOOLS = [
|
|
|
135
135
|
required: ["nodes"],
|
|
136
136
|
},
|
|
137
137
|
},
|
|
138
|
+
{
|
|
139
|
+
name: "get_schema",
|
|
140
|
+
description:
|
|
141
|
+
"One element type's parameters, on demand. This is the other half of " +
|
|
142
|
+
"list_ops: that returns the vocabulary of N, this returns the " +
|
|
143
|
+
"vocabulary of E. Call it for the type you are about to write rather " +
|
|
144
|
+
"than carrying every type's parameters in context \u2014 that is the " +
|
|
145
|
+
"difference between paying for a schema once and paying for it in " +
|
|
146
|
+
"every request. Each entry names the mapper, the components it builds " +
|
|
147
|
+
"and every parameter recovered from the source those components " +
|
|
148
|
+
"actually read, so it cannot describe a parameter the library does " +
|
|
149
|
+
"not have. Omit `type` for the whole schema. Composites carry content " +
|
|
150
|
+
"in a slot \u2014 `items` for cards, nav, sideNav, table and ulist; " +
|
|
151
|
+
"`children` for row, form and wrap \u2014 and declaring it in the " +
|
|
152
|
+
"other one renders the placeholders instead.",
|
|
153
|
+
inputSchema: {
|
|
154
|
+
type: "object",
|
|
155
|
+
properties: {
|
|
156
|
+
type: {
|
|
157
|
+
type: "string",
|
|
158
|
+
description: "An element type, e.g. \"cards\". Omit for the whole schema.",
|
|
159
|
+
},
|
|
160
|
+
},
|
|
161
|
+
},
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
name: "parse_html",
|
|
165
|
+
description:
|
|
166
|
+
"Read a rendered page back into an E array, so a page can be EDITED " +
|
|
167
|
+
"rather than only generated: parse it, change the one thing, render " +
|
|
168
|
+
"again. Two tiers, and the report says which one you got. A page " +
|
|
169
|
+
"rendered with `{annotate: true}` carries its own descriptors and " +
|
|
170
|
+
"comes back exactly \u2014 every type, every option, nothing " +
|
|
171
|
+
"inferred. Without that, only what the tag settles is recovered: " +
|
|
172
|
+
"headings, paragraphs, links, images and lists. Thirteen composite " +
|
|
173
|
+
"types render as a bare <div> with nothing to tell them apart, so " +
|
|
174
|
+
"those are reported unrecovered rather than guessed \u2014 a wrong " +
|
|
175
|
+
"guess would silently become a different page. The recovered spec is " +
|
|
176
|
+
"validated before it is returned, because a descriptor read out of a " +
|
|
177
|
+
"document is untrusted input.",
|
|
178
|
+
inputSchema: {
|
|
179
|
+
type: "object",
|
|
180
|
+
properties: {
|
|
181
|
+
html: { type: "string", description: "The rendered HTML to read back." },
|
|
182
|
+
},
|
|
183
|
+
required: ["html"],
|
|
184
|
+
},
|
|
185
|
+
},
|
|
138
186
|
{
|
|
139
187
|
name: "preview",
|
|
140
188
|
description:
|
|
@@ -180,6 +228,44 @@ const IMPL = {
|
|
|
180
228
|
validate_nodes: async ({ nodes, elements }) =>
|
|
181
229
|
ok(validateNodes(nodes, elements)),
|
|
182
230
|
|
|
231
|
+
// Served from the shipped schema.json rather than regenerated: the
|
|
232
|
+
// generator is a build-time script and this server answers in-process. The
|
|
233
|
+
// drift test keeps the committed copy honest, so reading it is not a second
|
|
234
|
+
// source of truth, it is the same one at rest.
|
|
235
|
+
get_schema: async ({ type } = {}) => {
|
|
236
|
+
const [{ readFile }, { fileURLToPath }, { dirname, join }] = await Promise.all([
|
|
237
|
+
import("node:fs/promises"), import("node:url"), import("node:path"),
|
|
238
|
+
]);
|
|
239
|
+
const here = dirname(fileURLToPath(import.meta.url));
|
|
240
|
+
const schema = JSON.parse(await readFile(join(here, "..", "schema.json"), "utf8"));
|
|
241
|
+
const types = schema.types || {};
|
|
242
|
+
if (!type) return ok(schema);
|
|
243
|
+
if (!types[type]) {
|
|
244
|
+
// Same report shape as everything else, so an agent parses one thing.
|
|
245
|
+
return ok({
|
|
246
|
+
ok: false,
|
|
247
|
+
errors: [{
|
|
248
|
+
code: "UNKNOWN_ELEMENT_TYPE", path: "type", got: type,
|
|
249
|
+
suggestions: Object.keys(types)
|
|
250
|
+
.filter((t) => t.slice(0, 2) === String(type).slice(0, 2)).slice(0, 3),
|
|
251
|
+
valid: Object.keys(types),
|
|
252
|
+
}],
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
return ok({ type, ...types[type] });
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
parse_html: async ({ html }) => {
|
|
259
|
+
// Same arrangement as `preview`: a DOM is a build-time concern, so jsdom
|
|
260
|
+
// is not bundled and its absence arrives as MISSING_PEER_DEPENDENCY from
|
|
261
|
+
// the handler below rather than as a stack trace.
|
|
262
|
+
const [{ JSDOM }, { parseReport }] = await Promise.all([
|
|
263
|
+
import("jsdom"), import("../lib/parse-html.js"),
|
|
264
|
+
]);
|
|
265
|
+
const dom = new JSDOM("<!DOCTYPE html><html><body></body></html>");
|
|
266
|
+
return ok(parseReport(String(html ?? ""), dom.window.document));
|
|
267
|
+
},
|
|
268
|
+
|
|
183
269
|
preview: async ({ elements, nodes, output }) => {
|
|
184
270
|
const N = nodes || [];
|
|
185
271
|
const report = validateNodes(N, elements);
|
package/bin/nodality.js
CHANGED
|
@@ -64,6 +64,13 @@ function showUsage() {
|
|
|
64
64
|
# --dir=<path> copy SKILL.md anywhere
|
|
65
65
|
# --no-mcp skip MCP registration
|
|
66
66
|
# Re-run after upgrading to refresh in place.
|
|
67
|
+
nodality schema [type] [--check] # Print the machine-readable element
|
|
68
|
+
# schema, derived from the source
|
|
69
|
+
# at run time. With a type, print
|
|
70
|
+
# just that type — the form an
|
|
71
|
+
# agent puts in its context.
|
|
72
|
+
# --check exit 1 if schema.json
|
|
73
|
+
# is stale (used in CI)
|
|
67
74
|
nodality help
|
|
68
75
|
|
|
69
76
|
Compile flags:
|
|
@@ -872,6 +879,11 @@ async function main() {
|
|
|
872
879
|
await runFanoutStandalone(rest);
|
|
873
880
|
} else if (command === "stage") {
|
|
874
881
|
await runStage(rest);
|
|
882
|
+
} else if (command === "schema") {
|
|
883
|
+
// Lazily imported like `mcp` and `skill`: a subcommand nobody invoked
|
|
884
|
+
// should cost nothing, and a broken generator must not take the CLI down.
|
|
885
|
+
const { runSchema } = await import("./schema-cli.mjs");
|
|
886
|
+
await runSchema(rest);
|
|
875
887
|
} else if (command === "skill") {
|
|
876
888
|
const { runSkillInstall } = await import("./install-skill.mjs");
|
|
877
889
|
await runSkillInstall(rest);
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// bin/schema-cli.mjs — `npx nodality schema [type] [--check]`
|
|
2
|
+
//
|
|
3
|
+
// Stage 2 of AGENTIC-FIRST-PLAN.md. The point of the subcommand is property 2
|
|
4
|
+
// of "agentic-first": schema ON DEMAND rather than schema in context. A model
|
|
5
|
+
// that can fetch one type's parameters pays for that type once, instead of
|
|
6
|
+
// carrying every type's vocabulary in every request.
|
|
7
|
+
//
|
|
8
|
+
// TWO SOURCES, in order, because the first one is not always there.
|
|
9
|
+
//
|
|
10
|
+
// In a checkout the generator runs and the schema is rebuilt from source, so
|
|
11
|
+
// what an agent is told cannot be staler than the library it is talking to.
|
|
12
|
+
// In an INSTALLED package it is read from the shipped schema.json instead.
|
|
13
|
+
//
|
|
14
|
+
// That second path is not belt-and-braces, it is a bug fix. `schema.json` and
|
|
15
|
+
// `scripts/` were both outside package.json's `files`, so neither reached the
|
|
16
|
+
// tarball, and `npx nodality schema` failed with MODULE_NOT_FOUND for every
|
|
17
|
+
// consumer while working perfectly in the dev tree — property 2 shipped as
|
|
18
|
+
// nothing at all. Both are packaged now, and `packaging/smoke.mjs` runs this
|
|
19
|
+
// subcommand against the packed tarball so the surface cannot regress
|
|
20
|
+
// invisibly again.
|
|
21
|
+
import { spawn } from "node:child_process";
|
|
22
|
+
import { fileURLToPath } from "node:url";
|
|
23
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
24
|
+
import path from "node:path";
|
|
25
|
+
|
|
26
|
+
export async function runSchema(args) {
|
|
27
|
+
const here = path.dirname(fileURLToPath(import.meta.url));
|
|
28
|
+
const gen = path.join(here, "..", "scripts", "generate-schema.mjs");
|
|
29
|
+
const committed = path.join(here, "..", "schema.json");
|
|
30
|
+
const type = args.find((a) => !a.startsWith("--"));
|
|
31
|
+
|
|
32
|
+
if (existsSync(gen)) {
|
|
33
|
+
const passthrough = args.includes("--check")
|
|
34
|
+
? ["--check"]
|
|
35
|
+
: type ? ["--type", type] : ["--stdout"];
|
|
36
|
+
await new Promise((resolve) => {
|
|
37
|
+
const p = spawn(process.execPath, [gen, ...passthrough], { stdio: "inherit" });
|
|
38
|
+
p.on("exit", (code) => { process.exitCode = code ?? 0; resolve(); });
|
|
39
|
+
});
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (!existsSync(committed)) {
|
|
44
|
+
console.error("[nodality] no schema available: neither scripts/generate-schema.mjs");
|
|
45
|
+
console.error(" nor schema.json is present in this installation.");
|
|
46
|
+
process.exitCode = 1;
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// `--check` asks whether the committed copy matches what the source would
|
|
51
|
+
// produce. Without the generator that question cannot be answered, and
|
|
52
|
+
// answering "yes" from the file being checked would be circular.
|
|
53
|
+
if (args.includes("--check")) {
|
|
54
|
+
console.error("[nodality] --check needs scripts/generate-schema.mjs, which is not");
|
|
55
|
+
console.error(" present in an installed package. Run it from a checkout.");
|
|
56
|
+
process.exitCode = 1;
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const schema = JSON.parse(readFileSync(committed, "utf8"));
|
|
61
|
+
if (type) {
|
|
62
|
+
const entry = schema.types?.[type];
|
|
63
|
+
if (!entry) {
|
|
64
|
+
console.error(`unknown type "${type}"`);
|
|
65
|
+
process.exitCode = 1;
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
console.log(JSON.stringify({ type, ...entry }, null, 2));
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
process.stdout.write(JSON.stringify(schema, null, 2) + "\n");
|
|
72
|
+
}
|