nodality 1.1.14 → 1.2.0
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 +41 -5
- package/bin/nodality.js +61 -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 +60 -1
- 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 +60 -1
- package/dist/designer.esm.js +1 -1
- package/dist/designer.esm.js.LICENSE.txt +60 -1
- 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 +60 -1
- 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 +60 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.esm.js +1 -1
- package/dist/index.esm.js.LICENSE.txt +60 -1
- 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 +1 -1
- package/dist/text-field.cjs.js.LICENSE.txt +1 -1
- package/dist/text-field.esm.js +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 +6 -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 +13 -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 +347 -0
- package/lib/card-getter.js +1 -1
- package/lib/codegen.js +1 -1
- package/lib/data.js +1 -1
- package/lib/designer.js +22 -1
- package/lib/element-mapper.js +2 -1
- package/lib/keyframe-animation.js +1 -1
- package/lib/link-getter.js +1 -1
- package/lib/morph-node.js +47 -8
- 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 +196 -32
- package/lib/webmcp-adapter.js +307 -0
- package/package.json +1 -1
package/bin/mcp-server.mjs
CHANGED
|
@@ -76,9 +76,19 @@ const NODES_SCHEMA = {
|
|
|
76
76
|
"array order); `{ op: { name: \"shadow\" }, target: [...] }` is a " +
|
|
77
77
|
"design node; `{ op: \"morph\", from: \"topnav\", to: { \"About\": " +
|
|
78
78
|
"\"about\" }, effect: \"t-vhs\", duration: 900, back: true }` is a " +
|
|
79
|
-
"transition — one element becomes another on interaction.
|
|
80
|
-
"
|
|
81
|
-
"`from
|
|
79
|
+
"transition — one element becomes another on interaction. A morph " +
|
|
80
|
+
"describes a whole navigation graph by carrying `chain` instead of one " +
|
|
81
|
+
"`from`/`to`: `{ op: \"morph\", effect: \"t-vhs\", duration: 620, " +
|
|
82
|
+
"back: true, chain: [ { from: \"home\", to: { \"Work\": \"work\" } }, " +
|
|
83
|
+
"{ from: \"work\", to: { \"Detail\": \"detail\" }, effect: \"t-split\" } " +
|
|
84
|
+
"] }`. The entries are EDGES, not keyframes: edge two is reachable " +
|
|
85
|
+
"FROM the state edge one lands on, so a landed state becomes a source. " +
|
|
86
|
+
"Settings on the node are defaults each edge may override, and `chain` " +
|
|
87
|
+
"wins outright — node-level `from`/`to` are not read beside it. " +
|
|
88
|
+
"Nothing in N names a component; the two arrays meet only through " +
|
|
89
|
+
"`target`, `from` and `to`, each of which names an element id, written " +
|
|
90
|
+
"either bare (\"work\") or in selector form (\"#work\"). Call list_ops " +
|
|
91
|
+
"first for the exact vocabulary.",
|
|
82
92
|
items: { type: "object" },
|
|
83
93
|
};
|
|
84
94
|
|
|
@@ -199,13 +209,39 @@ const IMPL = {
|
|
|
199
209
|
},
|
|
200
210
|
});
|
|
201
211
|
|
|
202
|
-
const
|
|
212
|
+
const html = await readFile(out, "utf8");
|
|
213
|
+
const bytes = Buffer.byteLength(html);
|
|
214
|
+
|
|
215
|
+
// The surface this pair would give an OPERATING agent, reported to
|
|
216
|
+
// the GENERATING one. The two loops meet here: a model writing the
|
|
217
|
+
// page can see the tools a model using the page will be handed, and
|
|
218
|
+
// can tell before shipping that a form it meant to expose derived
|
|
219
|
+
// nothing. Lifted out of the rendered page rather than derived a
|
|
220
|
+
// second time, so what is reported is what the build emitted.
|
|
221
|
+
let surface;
|
|
222
|
+
const at = html.indexOf('id="nodality-agent-manifest"');
|
|
223
|
+
if (at >= 0) {
|
|
224
|
+
const s = html.indexOf(">", at);
|
|
225
|
+
const e = html.indexOf("</script>", s);
|
|
226
|
+
if (s >= 0 && e > s) {
|
|
227
|
+
try {
|
|
228
|
+
const m = JSON.parse(html.slice(s + 1, e));
|
|
229
|
+
surface = {
|
|
230
|
+
tools: m.tools.map((x) => ({ name: x.name, description: x.description })),
|
|
231
|
+
views: m.views || null,
|
|
232
|
+
};
|
|
233
|
+
} catch { /* a malformed declaration is simply not reported */ }
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
203
237
|
return ok({
|
|
204
238
|
path: out, bytes,
|
|
239
|
+
...(surface ? { surface } : {}),
|
|
205
240
|
// Said plainly, because an agent cannot see the result and would
|
|
206
241
|
// otherwise report a shader that never ran as working.
|
|
207
242
|
note: "Prerendered DOM only. Raster effects and morph transitions " +
|
|
208
|
-
"need a GPU and run when this file is opened in a browser."
|
|
243
|
+
"need a GPU and run when this file is opened in a browser." +
|
|
244
|
+
(surface ? " `surface` is what an agent operating this page would be offered." : ""),
|
|
209
245
|
});
|
|
210
246
|
},
|
|
211
247
|
};
|
package/bin/nodality.js
CHANGED
|
@@ -596,6 +596,67 @@ async function runPrerender(rawArgs) {
|
|
|
596
596
|
}
|
|
597
597
|
|
|
598
598
|
await prerenderSite(config);
|
|
599
|
+
writeAgentManifest(config);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Lift the agent surface out of the prerendered pages into one file.
|
|
604
|
+
*
|
|
605
|
+
* Nothing derives anything here. The declaration was written into each
|
|
606
|
+
* document by the SAME code that registers the tools at runtime, so by
|
|
607
|
+
* the time prerendering has finished it is already serialised inside the
|
|
608
|
+
* static HTML — this only gathers it up, so that a consumer which wants
|
|
609
|
+
* capability without parsing pages has one URL to fetch. That is the
|
|
610
|
+
* half of the agent story that needs no browser support, no origin
|
|
611
|
+
* trial and no standard: a crawler, an indexer, or an agent deciding
|
|
612
|
+
* whether the site is worth visiting reads it without executing
|
|
613
|
+
* anything.
|
|
614
|
+
*
|
|
615
|
+
* Byte-stability matters and is asserted in the suite: the file ships
|
|
616
|
+
* from a build, so it inherits the determinism the whole model rests on
|
|
617
|
+
* — pages are visited in sorted order and nothing here is timestamped.
|
|
618
|
+
*/
|
|
619
|
+
function writeAgentManifest(config) {
|
|
620
|
+
const uploadDir = path.resolve(config.uploadDir || "upload");
|
|
621
|
+
const MANIFEST_ID = "nodality-agent-manifest";
|
|
622
|
+
const pages = {};
|
|
623
|
+
|
|
624
|
+
const scan = (dir, prefix = "") => {
|
|
625
|
+
let entries;
|
|
626
|
+
try { entries = fs.readdirSync(dir, { withFileTypes: true }); } catch { return; }
|
|
627
|
+
for (const e of entries.sort((a, b) => a.name.localeCompare(b.name))) {
|
|
628
|
+
const abs = path.join(dir, e.name);
|
|
629
|
+
if (e.isDirectory()) {
|
|
630
|
+
if (["node_modules", "dist", "lib", "layout", "assets", "p"].includes(e.name)) continue;
|
|
631
|
+
scan(abs, prefix + e.name + "/");
|
|
632
|
+
continue;
|
|
633
|
+
}
|
|
634
|
+
if (!e.name.endsWith(".html")) continue;
|
|
635
|
+
const html = fs.readFileSync(abs, "utf8");
|
|
636
|
+
// Located by id rather than parsed: the file is emitted by us, and
|
|
637
|
+
// a dependency-free substring read cannot be broken by whatever a
|
|
638
|
+
// page happens to contain elsewhere.
|
|
639
|
+
const open = html.indexOf(`id="${MANIFEST_ID}"`);
|
|
640
|
+
if (open < 0) continue;
|
|
641
|
+
const start = html.indexOf(">", open);
|
|
642
|
+
const end = html.indexOf("</script>", start);
|
|
643
|
+
if (start < 0 || end < 0) continue;
|
|
644
|
+
try {
|
|
645
|
+
pages[prefix + e.name] = JSON.parse(html.slice(start + 1, end));
|
|
646
|
+
} catch { /* a page that did not finish rendering is simply absent */ }
|
|
647
|
+
}
|
|
648
|
+
};
|
|
649
|
+
scan(uploadDir);
|
|
650
|
+
|
|
651
|
+
const out = path.join(uploadDir, "agent-manifest.json");
|
|
652
|
+
if (!Object.keys(pages).length) {
|
|
653
|
+
// No page declared a surface: remove a stale file rather than leave
|
|
654
|
+
// one claiming capabilities the site no longer offers.
|
|
655
|
+
if (fs.existsSync(out)) fs.unlinkSync(out);
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
fs.writeFileSync(out, JSON.stringify({ origin: config.origin || null, pages }, null, 2) + "\n");
|
|
659
|
+
console.log(`✅ Agent manifest — ${Object.keys(pages).length} page(s) → agent-manifest.json`);
|
|
599
660
|
}
|
|
600
661
|
|
|
601
662
|
// ─── compile subcommand ────────────────────────────────────────
|