@plitzi/sdk-mcp 0.38.3 → 0.38.4
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/CHANGELOG.md +203 -0
- package/dist/modules/mcp/helpers/guide.js +42 -11
- package/dist/modules/mcp/localScreenshotClient.d.ts +3 -0
- package/dist/modules/mcp/localScreenshotClient.js +2 -0
- package/dist/modules/mcp/resources/explain.js +1 -1
- package/dist/modules/mcp/server.js +1 -1
- package/dist/modules/mcp/tools/apply/index.d.ts +1 -0
- package/dist/modules/mcp/tools/operations/index.d.ts +4 -0
- package/dist/modules/mcp/tools/operations/schema/elements/patchElement.d.ts +1 -0
- package/dist/modules/mcp/tools/operations/schema/elements/patchElement.js +5 -2
- package/dist/modules/mcp/tools/operations/schema/elements/upsertElement.js +1 -0
- package/dist/modules/mcp/tools/operations/schema/operations.d.ts +1 -0
- package/dist/modules/mcp/tools/operations/schema/shared.d.ts +4 -0
- package/dist/modules/mcp/tools/operations/schema/shared.js +11 -2
- package/dist/modules/mcp/tools/operations/schema/write.js +2 -1
- package/dist/modules/mcp/tools/operations/schemaIds.js +2 -1
- package/dist/modules/mcp/tools/preview.d.ts +1 -0
- package/dist/modules/mcp/tools/render.d.ts +1 -0
- package/dist/modules/mcp/tools/screenshot.d.ts +1 -0
- package/dist/modules/mcp/tools/validate.d.ts +1 -0
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,208 @@
|
|
|
1
1
|
# @plitzi/sdk-mcp
|
|
2
2
|
|
|
3
|
+
## 0.38.4
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 6ae4161: ## `plitzi push`: a self-hosted project back on its space
|
|
8
|
+
|
|
9
|
+
`plitzi create --from` and `plitzi pull` took a space out as a project and kept it in step; nothing put the project's
|
|
10
|
+
own changes back but a command per part, and no command at all for its pages. `plitzi push` is the way back
|
|
11
|
+
(`docs/en/projects-from-spaces.md`):
|
|
12
|
+
|
|
13
|
+
- **What changed, or what is named.** `plitzi push` sends what changed since the project last had the space — at a
|
|
14
|
+
terminal, offered as a ticked list to choose from (`↑/↓`, space, Enter); `plitzi push space functions` sends only
|
|
15
|
+
those parts: `space`, `functions`, `runtime`, `plugins`.
|
|
16
|
+
- **In order:** each changed plugin packed and uploaded (`pack plugin` + `upload plugin`, `--cdn`/`--bucket`), the
|
|
17
|
+
functions, the runtime, then the space — `src/space.ts` authored, the actions `src/actions.ts` serves and the manifests
|
|
18
|
+
in `src/connectors/` — as the space's draft. Never a published environment.
|
|
19
|
+
- **Never over the builder's work unseen.** The export now carries which state the draft is in (`SpaceExport.draft`),
|
|
20
|
+
recorded in `.plitzi/space.json` by `create --from` and `pull`; a push names it, and a draft edited since is refused
|
|
21
|
+
until `--force`. A project that never had the space may take one nobody has worked on; one holding work takes
|
|
22
|
+
`--force`.
|
|
23
|
+
- **Then `pull` follows it.** `.plitzi/space.json` records what was sent — only that, so a builder's change to a part
|
|
24
|
+
not pushed is still the next pull's — and a project that started on its own works with `pull` from then on.
|
|
25
|
+
- `@plitzi/sdk-shared/source`: `SpaceImport` / `SpaceImportResult` (`SPACE_IMPORT_FORMAT`), the push's one shape for
|
|
26
|
+
both ends, beside `SpaceExport`, which gains `draft`.
|
|
27
|
+
- `functions push`, `runtime push` and `upload plugin` keep their behaviour; their cores are what `push` runs.
|
|
28
|
+
|
|
29
|
+
## A project's folders: `tmp/` for what it writes, `.plitzi/` committed, `public/` said to be public
|
|
30
|
+
- **`tmp/` is what a project writes for itself.** `@plitzi/sdk-server` keeps the plugins it builds in `tmp/.sdk-plugins`
|
|
31
|
+
and resized pictures in `tmp/images` by default (were `.sdk-plugins` and `.plitzi/images`). A project the CLI writes
|
|
32
|
+
puts the port it took (`tmp/dev-server.json`), the space as last authored while developing (`tmp/space.json`) and
|
|
33
|
+
Playwright's output (`tmp/visual`) there too, and its `.gitignore` ignores `tmp` — one line for all of it.
|
|
34
|
+
- **`.plitzi/` is committed.** The scaffold ignored it whole, so a clone lost `space.json`, `functions.json` and
|
|
35
|
+
`scaffold.json` — what `pull`, `push`, `functions push` and `upgrade` stand on. Now it holds only what the CLI records.
|
|
36
|
+
`npx plitzi upgrade --write` brings an existing project's `.gitignore` up.
|
|
37
|
+
- **No `space/offline-data.json`.** `npm run author` checks the space and writes nothing; the server asks it for the
|
|
38
|
+
documents with `--out tmp/space.json` while developing. The space is `src/space.ts`, and nothing beside it says
|
|
39
|
+
otherwise.
|
|
40
|
+
- **`public/` is on the internet.** The generated `README.md` and `AGENTS.md`, the CLI and authoring skills, the MCP
|
|
41
|
+
guide, `@plitzi/sdk-server`'s README and the docs now say so where data goes: never a secret, a key or data only
|
|
42
|
+
some visitors may read — in `public/`, or in a space's documents, which reach every visitor too.
|
|
43
|
+
|
|
44
|
+
## An agent leaves the project clean
|
|
45
|
+
|
|
46
|
+
`AGENTS.md` gains **Keep the project clean** — nothing unused left behind, scratch work in `tmp/`, one of everything,
|
|
47
|
+
files a reader can find, and `author`, `typecheck`, `lint`, `format` and `check` passing — and the authoring skill's
|
|
48
|
+
review checklist a **Nothing left behind** section.
|
|
49
|
+
|
|
50
|
+
## The dev tools' X-ray is the outlines too
|
|
51
|
+
|
|
52
|
+
The QA tab had **Outlines** (every element's box, its type and id when pointed at) and **X-ray** (the same boxes,
|
|
53
|
+
fainter, with what is wired to each). They are one tool now: the X-ray draws every box with its type and id, and marks
|
|
54
|
+
the wiring picked — all of it, one kind, or **Boxes only**.
|
|
55
|
+
|
|
56
|
+
## A new space that says where to go
|
|
57
|
+
|
|
58
|
+
The space a new account and `plitzi create` start from keeps its welcome, and gains the three ways to change it — the
|
|
59
|
+
builder, code (with the command to run) and an agent — before the guides, which are shorter. Header, navigation, main
|
|
60
|
+
and footer are landmarks; the grid behind the top fades out instead of ending at an edge; the footer's line spans the
|
|
61
|
+
content; the links say their words and icon themselves, with no suggestion left.
|
|
62
|
+
|
|
63
|
+
## Server data reads the same everywhere
|
|
64
|
+
- **One shape for a provider with a `query`.** A `runtime: 'server'` provider that only reads a JSON file the server
|
|
65
|
+
serves answered the body itself, while the same provider in the browser publishes `{ status, data }` — so moving it
|
|
66
|
+
to the server broke every binding. `publicFileResolver` and the builder's mock now answer `{ status, data }` too:
|
|
67
|
+
`<source>.data.<field>` whichever runtime.
|
|
68
|
+
- **Server data is on unless a space turns it off.** The page render read a missing `rsc` as on and the connector
|
|
69
|
+
resolver as off, so a server provider in a space the builder or the MCP made (neither writes `rsc`) resolved to
|
|
70
|
+
nothing, silently. Both read it as on now; only `rsc: { enabled: false }` turns it off (and is warned with a server
|
|
71
|
+
element). `authorSpace` writes `enabled: true` for a space that has one.
|
|
72
|
+
- **Never inside a component.** The page server resolves a page's tree and its layouts only, so a server provider in a
|
|
73
|
+
component rendered nothing, silently. Refused now (`server-provider-in-component`), with the fix: the provider on
|
|
74
|
+
the page, the rows handed in as a prop.
|
|
75
|
+
- **Bindings held to the data.** `authorSpace` takes `data` — what a provider's `query` answers — and
|
|
76
|
+
`publicData(folder)` (`@plitzi/sdk-authoring/node`) reads it from `public/`. A binding onto a path the file does not
|
|
77
|
+
have is warned (`path-not-in-data`) with the keys it does have. Generated projects pass it.
|
|
78
|
+
- **`plitzi check` reads the data too.** A binding that reads a path its provider's answer lacks, a provider that
|
|
79
|
+
failed (once, not as every element it left empty) and the rows each list rendered (`dataIssues`). `--ssr` names what
|
|
80
|
+
the server's HTML lacks that the hydrated page has. The dev tools' badge and panel (`data-plitzi-devtools`) are hidden
|
|
81
|
+
while `check` and `shot` look.
|
|
82
|
+
|
|
83
|
+
## Authoring, clearer where agents tripped
|
|
84
|
+
- **`controls` on a button** (`aria-controls`): named by the element's id; authoring gives that element the anchor and
|
|
85
|
+
refuses an id the space lacks (`controls-unknown`); a saved document naming no anchor is warned
|
|
86
|
+
(`controls-no-anchor`). The accordion recipe uses it.
|
|
87
|
+
- **`live` on a container** (`aria-live`, `polite` or `assertive`) for words that change while a visitor reads them.
|
|
88
|
+
- **`subType: 'p'`** for a paragraph made of parts; `span-holds-block` covers it.
|
|
89
|
+
- **`formControl` types `search`, `url` and `tel`.**
|
|
90
|
+
- **Images:** no `src` draws the SDK's own placeholder (the CDN one answered 404); `resize: false` keeps a picture as
|
|
91
|
+
written; an SVG is never resized — `/_plitzi/img` redirects to it (`307`) instead of refusing it.
|
|
92
|
+
- **Messages:** an id taken by another page or layout names it and the id to write; a hyphenated source in a template
|
|
93
|
+
(`list_study-plans`) is explained as valid; an unknown CSS property says to write it in `customCss`; an unknown
|
|
94
|
+
variant on `custom` says it is never a prop of the component it hosts.
|
|
95
|
+
- **`plitzi explain` knows the helpers** — `bindTemplate`, `visibleWhen`, `variantFrom`, `activeOn`, `activeWhen`,
|
|
96
|
+
`when`, `named`, `scope`, `source`, `twig` — and `motion`, from the presets the SDK plays (`MOTION_ENTERS`,
|
|
97
|
+
`MOTION_TRIGGERS`, `MOTION_LOOPS`, now exported). `--list helpers` lists them.
|
|
98
|
+
- **`plitzi shot`** writes to `tmp/shots/` by default, and a full page shows the arrivals tied to the scroll as they
|
|
99
|
+
end. `inspectPage` no longer reports an image a hidden ancestor hides.
|
|
100
|
+
- **Style inspector:** `container-type` in Size.
|
|
101
|
+
- **New recipes:** `server-data.ts`, `accordion.ts`.
|
|
102
|
+
|
|
103
|
+
## Matching a page to another, measured
|
|
104
|
+
- **A whole page is the whole page.** The SDK scrolls a pane of its own, so `shot`'s full-page picture was one
|
|
105
|
+
screen; the pane is unrolled now (`unrollPage`) — the viewport untouched, so a `100vh` hero stays one screen.
|
|
106
|
+
- **`plitzi shot --compare` says why, not only how much.** Every lazy picture on both pages is loaded before they are
|
|
107
|
+
taken (`loadImages`), so a section no longer swings between 23 % and 40 % on how many covers had arrived. Each section
|
|
108
|
+
is compared where it is on the other page (`alignPictures` over row profiles): a page 400 px longer is said once, with
|
|
109
|
+
the section the drift starts at, instead of a footer with the same styles reading 100 %. And the texts both pages
|
|
110
|
+
have are paired (`pageTexts`, `compareTexts`), each with what it does differently there —
|
|
111
|
+
`h1 "Learn CSS" — font-size 68px → 60px · y +19px` — position less the drift of its section. `comparePictures` takes
|
|
112
|
+
its options as an object now (`{ regions, tolerance, align }`).
|
|
113
|
+
- **`--scheme` is the space's theme.** A space whose default is dark painted dark under `--scheme light`, and the file
|
|
114
|
+
said light. `check` and `shot` now set the `theme` cookie a visitor's toggle writes; left out, the space's default is
|
|
115
|
+
pictured and the file is named by the theme actually painted.
|
|
116
|
+
|
|
117
|
+
## `motion: { on: 'view' }` arrives once
|
|
118
|
+
|
|
119
|
+
`view` was tied to the scroll both ways: cards faded out again as the reader scrolled back up. Now it plays once, the
|
|
120
|
+
first time the element comes into view, with its `duration`, and stays — `revealOnView` (`@plitzi/sdk-shared/schema/
|
|
121
|
+
motionReveal`), one observer under the SDK's root, marks it `data-motion-seen`. The scroll-driven arrival is
|
|
122
|
+
`on: 'scroll'`. A page read without scripts shows them as they end (`@media (scripting: none)`); the builder's previews
|
|
123
|
+
and the MCP's local screenshots hold motion at its end. The builder's Motion tab has the three.
|
|
124
|
+
|
|
125
|
+
The builder's preview plays motion as the published page does. It held everything at its end, and nothing marked
|
|
126
|
+
the canvas `data-hydrated`, so neither the loops nor a space's own `[data-hydrated]` animations ever started there.
|
|
127
|
+
Now an arrival plays as it comes into view, and the loops and keyframes run; **▶** on the canvas being edited runs the
|
|
128
|
+
space's own `[data-hydrated]` loops too. The motion guide adds the rule this needs from a space: `[data-hydrated]` is for
|
|
129
|
+
loops; an entrance of its own that plays once (`transform`/`opacity` only) plays from the first paint with
|
|
130
|
+
`backwards`, as the presets do — gated on hydration it jumps when the page goes live, and a canvas that never goes
|
|
131
|
+
live holds it on its first frame.
|
|
132
|
+
|
|
133
|
+
## Thirteen ways in, nine loops
|
|
134
|
+
|
|
135
|
+
`motion` grows from six arrivals and four loops to thirteen and nine, all still `opacity` and the transforms:
|
|
136
|
+
|
|
137
|
+
- **Bold arrivals:** `slide-up` (from well below), `zoom-in` (from 60%), `zoom-out` (settling from 125%), `tilt`
|
|
138
|
+
(rising as it turns straight), `spin-in` (half a turn as it grows).
|
|
139
|
+
- **Springy arrivals:** `pop` overshoots and settles; `bounce-in` falls into place and bounces.
|
|
140
|
+
- **Loops:** `bounce`, `wobble`, `orbit` (a slow circle round where it is), `heartbeat`, `drift`.
|
|
141
|
+
|
|
142
|
+
An arrival is now a list of frames (`MOTION_ENTER_FRAMES` in `@plitzi/sdk-shared/schema/motion`; `MOTION_ENTER_FROM`
|
|
143
|
+
is its first), and so is a loop (`MOTION_LOOP_FRAMES[name].frames`, replacing `transform`/`at`). Arrivals move the
|
|
144
|
+
individual `translate`, `scale` and `rotate`, so they still compose with an element's own `transform` and with a loop.
|
|
145
|
+
The builder's Motion tab previews every frame; authoring, the MCP, `explain motion` and GraphQL read the same lists.
|
|
146
|
+
|
|
147
|
+
An arrival from the side no longer scrolls the page sideways. `slide-left` starts 32px to the right of where it lands,
|
|
148
|
+
past a phone's 16px gutter, and until it had played the page could be dragged sideways. The SDK's root clips that way
|
|
149
|
+
now (`overflow-x: clip`, which keeps the window the scroller: sticky bars and scroll timelines are untouched), and the
|
|
150
|
+
builder's preview does the same. Content wider than the page is cut rather than scrolling the page — give it a box of
|
|
151
|
+
its own with `overflow-x: auto`.
|
|
152
|
+
|
|
153
|
+
**3D and the transform parts are style properties.** `transform-style`, `perspective-origin`, `backface-visibility`,
|
|
154
|
+
`translate`, `rotate` and `scale` join the vocabulary (they were refused as `css-property-unknown` and had to go in
|
|
155
|
+
`customCss`); `scale: 0.94` is a factor, not pixels.
|
|
156
|
+
|
|
157
|
+
**The builder's placeholder for an empty element is 24px** (was 50px), one size for every element that has one. It
|
|
158
|
+
is a minimum, so it also grew empty shapes with a size of their own — a dot, a planet — while editing; 24px is still
|
|
159
|
+
a box to see, pick and drop into.
|
|
160
|
+
|
|
161
|
+
The desktop app's window was blank: authoring, run in the renderer to build the rail, asked Vite's `process` shim for
|
|
162
|
+
a working directory it does not have. It reads one only where there is one now — and only when a class conflict is
|
|
163
|
+
reported, rather than for every element of every space it writes.
|
|
164
|
+
|
|
165
|
+
## Authoring advice that knows where and when
|
|
166
|
+
- **`class-conflict` says where both declarations are:** `styles('md-menu-button') at src/components/dropdown.ts:12,
|
|
167
|
+
used by button at …, and styles('md-menu-button') at src/site/layout.ts:8, used by …` — `styles()` records its line as
|
|
168
|
+
an element factory does.
|
|
169
|
+
- **`repeated-shape` leaves controls alone.** Siblings that read different sources or write different state keys — a
|
|
170
|
+
menu for the language, one for the level — are not offered as a list.
|
|
171
|
+
- **`quiet: ['repeated-shape']`** on an element says a suggestion was left on purpose, and it is not offered again.
|
|
172
|
+
Only suggestions' codes (`quiet-unknown`). It is saved on the element (`definition.quiet`), so the builder's problems
|
|
173
|
+
panel, the MCP's `upsertElement`/`patchElement` and a project pulled back with `plitzi pull` all leave it alone.
|
|
174
|
+
|
|
175
|
+
## What the docs say is what the code does
|
|
176
|
+
|
|
177
|
+
A pass across authoring's own messages, the skills, the MCP guide, `docs/en`, the CLI's README and the website, so an
|
|
178
|
+
agent reading two of them is never told two things:
|
|
179
|
+
|
|
180
|
+
- **A binding's `source` is the bound value, and only that.** With no value yet it fell back to the attribute's
|
|
181
|
+
current one — `sourceTo` — so `{{ source|default('…') }}` never took its default and `{{ source ? … }}` read an
|
|
182
|
+
element's placeholder ("Text") as an answer. It is `undefined` until the source has a value now; `sourceTo` is still
|
|
183
|
+
the value before.
|
|
184
|
+
- **`explain` writes a step the way its builder is called:** `delay(ms)`, `openModal('modal-id', data?)`,
|
|
185
|
+
`scrollBy('row-id', { x: '80%' })` — not `delay(…)` above the document's param names, which read as `delay({ time })`.
|
|
186
|
+
- **A page field nobody takes is told what it was probably for** — `seo` → `seoTitle` and `seoDescription` — instead of a
|
|
187
|
+
hint about keeping state appended to every one.
|
|
188
|
+
- Docs set straight: an element's id is `data-plitzi-el` in the page (`data-id` is the builder's, with debugging on);
|
|
189
|
+
a visibility condition writes nothing while its source has no value and is a yes or a no once it has one; `mobile`
|
|
190
|
+
is up to and including 48rem; `loadStrategy` defaults by type (`lazy` for a modal); the accessibility codes listed
|
|
191
|
+
in full everywhere (`embed-without-title`, `dropdown-without-control`, `controls-no-anchor`); the generated
|
|
192
|
+
`AGENTS.md` says a repeated block is a component and rows of data a list, as the skill does; `plitzi runtime` is
|
|
193
|
+
documented in the CLI's README, its skill and the website, which no longer says state across requests needs a
|
|
194
|
+
server of your own.
|
|
195
|
+
|
|
196
|
+
- Updated dependencies [6ae4161]
|
|
197
|
+
- @plitzi/sdk-authoring@0.38.4
|
|
198
|
+
- @plitzi/sdk-elements@0.38.4
|
|
199
|
+
- @plitzi/sdk-interactions@0.38.4
|
|
200
|
+
- @plitzi/sdk-schema@0.38.4
|
|
201
|
+
- @plitzi/sdk-shared@0.38.4
|
|
202
|
+
- @plitzi/sdk-style@0.38.4
|
|
203
|
+
- @plitzi/plitzi-sdk@0.38.4
|
|
204
|
+
- @plitzi/sdk-server@0.38.4
|
|
205
|
+
|
|
3
206
|
## 0.38.3
|
|
4
207
|
|
|
5
208
|
### Patch Changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BUILTIN_TRANSFORMERS, GLOBAL_SOURCES } from "@plitzi/sdk-authoring";
|
|
1
|
+
import { BUILTIN_TRANSFORMERS, GLOBAL_SOURCES, MOTION_ENTERS, MOTION_LOOPS } from "@plitzi/sdk-authoring";
|
|
2
2
|
//#region src/modules/mcp/helpers/guide.ts
|
|
3
3
|
var GLOBALS = GLOBAL_SOURCES.map((source) => `\`${source}\``).join(", ");
|
|
4
4
|
var OTHER_TRANSFORMERS = Object.keys(BUILTIN_TRANSFORMERS).filter((action) => action !== "twigTemplate").map((action) => `\`${action}\``).join(", ");
|
|
@@ -88,6 +88,12 @@ button/link needs words (an icon-only button a \`title\`), every field a \`label
|
|
|
88
88
|
image an \`alt\` or \`decorative: true\`; clicks go on a \`button\`/\`link\`, never a container; headings step down one
|
|
89
89
|
level at a time. \`plitzi_screenshot view:"accessibility"\` shows the tree and what has no name.
|
|
90
90
|
|
|
91
|
+
**Everything the space holds is public.** Its pages, variables, attributes, flow params and mock data ship to every
|
|
92
|
+
visitor's browser, and a file on a public bucket of its CDN is served to anyone who has its address. A key, a token or
|
|
93
|
+
data only some visitors may read never goes in any of them: a secret is a credential the owner attaches (a connector, an
|
|
94
|
+
action or a function names it, never carries it), and data for some visitors only comes from a \`runtime: "server"\`
|
|
95
|
+
provider or an action that checks who is asking.
|
|
96
|
+
|
|
91
97
|
**Touched elements must be malformation-free.** Editing an element also checks its CURRENT stored content and BLOCKS
|
|
92
98
|
the save on any \`Pre-existing malformation in element …\` error (a broken transformer, a malformed step, an attribute
|
|
93
99
|
it never reads) — even parts you did not touch. These are NOT from your change (the message says so); fix them in the
|
|
@@ -234,7 +240,8 @@ space already had is not repeated on every batch — and none of them blocks any
|
|
|
234
240
|
page being shown: the \`current\` state marks it (see *Pages & folders*).
|
|
235
241
|
- \`repeated-shape\` — one structure written again with other words: a **component** with props
|
|
236
242
|
(\`upsertComponent { fromRef }\` turns one copy into it), or, for sibling rows of data, one \`repeatElement\`/\`list\`.
|
|
237
|
-
A few cards a person rewords by hand can stay cards
|
|
243
|
+
A few cards a person rewords by hand can stay cards; siblings that read different data or keep different state are
|
|
244
|
+
controls written alike, and are not offered.
|
|
238
245
|
- \`content-attribute\` — a \`button\` or \`link\` whose children are only a \`text\` and/or a \`fontAwesome\`: its words
|
|
239
246
|
are its own \`content\` and the icon its \`icon\`. What the text's class adds (\`white-space: nowrap\`) moves to the
|
|
240
247
|
box's class — never the class itself; the icon's class goes in the \`icon\` slot.
|
|
@@ -242,7 +249,9 @@ space already had is not repeated on every batch — and none of them blocks any
|
|
|
242
249
|
\`states\`/\`ancestors\`, the SDK (reduced motion, the theme toggle's icons) or the space's notification look says.
|
|
243
250
|
- \`heavy-animation\` — keyframes that animate a size, a position, a blur, a shadow, or a colour in a loop: they stutter
|
|
244
251
|
while the page loads. Lighter, not shorter — see **Motion — good practices**.
|
|
245
|
-
\`plitzi://explain/<code>\` explains each. Take one unless the copies are about to diverge
|
|
252
|
+
\`plitzi://explain/<code>\` explains each. Take one unless the copies are about to diverge; one left on purpose is
|
|
253
|
+
quieted on an element it names — \`quiet: ["repeated-shape"]\` on \`upsertElement\`/\`patchElement\` (\`null\` removes it)
|
|
254
|
+
— and is not offered again, here, in the builder or in authoring. Suggestions' codes only.
|
|
246
255
|
|
|
247
256
|
## Readers: resources vs plitzi_search vs plitzi_read (do not confuse them)
|
|
248
257
|
Three ways to read, each for a different moment — pick by what you have in hand:
|
|
@@ -269,7 +278,7 @@ runtime wires by it — there is no second key and nothing to translate. Creatin
|
|
|
269
278
|
That name is the **wiring key**: a provider registers its data source as \`<type>_<name>\`, so a \`source\` you write
|
|
270
279
|
against a name resolves to that element at runtime. Rules for a **new** name (both enforced; a violation fails the
|
|
271
280
|
batch):
|
|
272
|
-
- Charset \`[A-Za-z0-9_-]\`, **starting with a letter** (e.g. \`"products-api"\`, \`"food_item"\`). A \`.\` would split
|
|
281
|
+
- Charset \`[A-Za-z0-9_-]\`, **starting with a letter** and not ending in \`-\` (e.g. \`"products-api"\`, \`"food_item"\`). A \`.\` would split
|
|
273
282
|
the \`<type>_<name>.<field>\` source path and the interaction target lookup, so **no dots**. An **underscore is
|
|
274
283
|
allowed**: the FIRST \`_\` separates \`<type>\` from the name and element types are camelCase with none, so
|
|
275
284
|
underscores inside a name are unambiguous (\`list_food_item\` → type \`list\`, name \`food_item\`).
|
|
@@ -281,7 +290,8 @@ batch):
|
|
|
281
290
|
**Where an element renders** is its \`runtime\`, settable on \`upsertElement\`/\`patchElement\`: \`"shared"\` (the
|
|
282
291
|
default, both sides), \`"client"\` (browser only) or \`"server"\` (SSR only). It matters for one thing above all — an
|
|
283
292
|
\`apiContainer\` reads through a **connector** only when it is \`"server"\` (see *Connectors*). An element read
|
|
284
|
-
reports it only when it is set.
|
|
293
|
+
reports it only when it is set. The page server resolves \`"server"\` elements of a page and its layouts only, never
|
|
294
|
+
inside a component — one there is refused; put the provider on the page and hand the component its rows as a prop.
|
|
285
295
|
|
|
286
296
|
**Renaming** (\`patchElement\` with \`rename\`) moves the one key: the parent's child list, every binding source and
|
|
287
297
|
every interaction target across the space that named the old one is repointed with it, so nothing comes unwired.
|
|
@@ -412,7 +422,9 @@ provider's records into a list element:
|
|
|
412
422
|
**What an \`apiContainer\` publishes** depends on where it reads. Through a connector (\`runtime: "server"\`) it is the
|
|
413
423
|
fixed shape under *Connectors* — \`.records\` or \`.record\`, \`.pageInfo\`, … With a browser \`query\` it is the
|
|
414
424
|
response: \`.data\` (the parsed body — an API answering \`{ "items": [...] }\` is read as
|
|
415
|
-
\`apiContainer_<name>.data.items\`) and \`.status\` (the HTTP status)
|
|
425
|
+
\`apiContainer_<name>.data.items\`) and \`.status\` (the HTTP status) — and a \`"server"\` provider with only a
|
|
426
|
+
\`query\` (a JSON file the deployment serves) answers in that same shape, so moving it to the server changes no
|
|
427
|
+
binding. Both add \`.isLoading\`, \`.isEmpty\`,
|
|
416
428
|
\`.hasError\` and \`.errorMessage\`.
|
|
417
429
|
|
|
418
430
|
**Source scope — a source is visible to the provider's DESCENDANTS only.** An element source named
|
|
@@ -435,7 +447,7 @@ the API needs a token or the content should be in the HTML), or a browser-side \
|
|
|
435
447
|
\`{ action, params }\`; the runtime runs them in order and resolves each by its \`action\` alone, so an **unknown
|
|
436
448
|
action is silently skipped** and the raw value passes through. Use the **exact** action names from
|
|
437
449
|
\`plitzi://data-sources\` (\`transformers\`). The most common is **\`twigTemplate\`** to format a value — the incoming
|
|
438
|
-
value is the **\`{{source}}\`** token (NOT \`{{value}}\`); \`{{sourceTo}}\` is the field's previous value. Example —
|
|
450
|
+
value is the **\`{{source}}\`** token (NOT \`{{value}}\`) — undefined until the source has a value, so \`{{ source|default('…') }}\` covers the wait; \`{{sourceTo}}\` is the field's previous value. Example —
|
|
439
451
|
show a number with units:
|
|
440
452
|
\`{ "type": "upsertBinding", "pageRef": "home", "ref": "food-item-time", "category": "attributes",
|
|
441
453
|
"binding": { "to": "content", "source": "list_food-list.item.cookTimeMinutes",
|
|
@@ -538,6 +550,20 @@ Discover valid actions in \`plitzi://interactions/{env}\`: \`actions\` = observe
|
|
|
538
550
|
node type and valid params per action. An element read lists its flows as ordered nodes (each with its \`id\` and
|
|
539
551
|
\`enabled\`), so a follow-up patch/delete needs no extra read.
|
|
540
552
|
|
|
553
|
+
## What is public — and where a secret goes
|
|
554
|
+
A space is served to anyone who opens it, and everything it is made of goes with it:
|
|
555
|
+
|
|
556
|
+
- **The documents.** Every page, layout and component, every schema and style variable, every attribute, binding,
|
|
557
|
+
flow param and \`mockData\` reaches the visitor's browser with the page. Hiding an element (\`visible: false\`, a
|
|
558
|
+
flag, a condition) does not remove it from what is sent.
|
|
559
|
+
- **The files.** A file on one of the space's public buckets is on the internet at its address, signed in or not —
|
|
560
|
+
for pictures, fonts and data every visitor may see.
|
|
561
|
+
|
|
562
|
+
So a secret — an API key, a token, a password — never goes in a document or a public file. It is a **credential**,
|
|
563
|
+
created by the space owner in the builder, which a connector, an action or a function **names** and never carries.
|
|
564
|
+
Data only some visitors may read comes from a \`runtime: "server"\` provider or a server action whose \`access\` checks
|
|
565
|
+
who is asking — never from a public file or a document the page filters on the client.
|
|
566
|
+
|
|
541
567
|
## Connectors — CMS and API integrations
|
|
542
568
|
A **connector** is how a space reads real content from Strapi, WordPress, Contentful, Directus or any REST service.
|
|
543
569
|
It is **a manifest, not code**: you declare the base URL, the endpoints, the auth template and the filter operators,
|
|
@@ -926,8 +952,10 @@ Space-level configuration lives in \`plitzi://settings/{env}\` and is edited wit
|
|
|
926
952
|
## Motion — good practices
|
|
927
953
|
A preset first: an element's \`motion\` field (\`upsertElement\`/\`patchElement\`) —
|
|
928
954
|
\`{ "enter": "fade-up", "on": "view" }\`, \`"stagger": 60\` for its children one by one, \`"loop": "float"\` — is
|
|
929
|
-
played by the SDK, cheap and stilled for reduced motion.
|
|
930
|
-
|
|
955
|
+
played by the SDK, cheap and stilled for reduced motion. \`on\`: \`load\` (default), \`view\` (once, the first time it
|
|
956
|
+
comes into view, then it stays) or \`scroll\` (follows the scroll both ways — it fades back out as the reader scrolls
|
|
957
|
+
up past it; only for an effect that is about the scroll itself). Enters: ${MOTION_ENTERS.join(", ")}; loops:
|
|
958
|
+
${MOTION_LOOPS.join(", ")}. Beyond them, keyframes go in \`customCss\` (\`patchSettings\`), a
|
|
931
959
|
definition names them (\`animation\`). Only \`opacity\` and
|
|
932
960
|
\`transform\` (\`translate\`, \`scale\`, \`rotate\`) animate off the main thread: they stay smooth while the page
|
|
933
961
|
hydrates and on a slow phone. Anything else repaints or lays the page out again on every frame, and freezes while the
|
|
@@ -940,7 +968,8 @@ page's scripts run.
|
|
|
940
968
|
pulsing glow is a static gradient whose \`opacity\` or \`scale\` changes.
|
|
941
969
|
- Decoration that must animate something else (a custom property, \`background-position\`) starts paused and runs
|
|
942
970
|
once the page is hydrated: \`.glow { animation: glow 8s linear infinite paused; } [data-hydrated] .glow {
|
|
943
|
-
animation-play-state: running; }\` in \`customCss\`.
|
|
971
|
+
animation-play-state: running; }\` in \`customCss\`. That is for loops: an entrance of its own that plays once
|
|
972
|
+
(\`transform\`/\`opacity\` only) plays from the first paint with \`backwards\`, never gated on \`[data-hydrated]\`.
|
|
944
973
|
- Entrances: \`opacity\` + a small \`translateY\`, under ~600ms, staggered by tens of ms.
|
|
945
974
|
- One slow ambient loop per screen at most — not one per card: \`infinite\` runs on every visitor's battery.
|
|
946
975
|
- Name what transitions (\`transition: transform 200ms, opacity 200ms\`), never \`all\`; \`will-change\` only on the
|
|
@@ -962,7 +991,9 @@ tree names nothing is invisible to both, however it looks. So build every page t
|
|
|
962
991
|
no agent finds them. An empty backdrop that closes a panel is the exception (the panel's close button and Escape
|
|
963
992
|
are the ways everyone has).
|
|
964
993
|
- **State is said, not only styled.** A toggle sets \`ariaPressed\`, a button that opens a panel \`ariaExpanded\`
|
|
965
|
-
(bind them like any attribute) — an "active" class alone is invisible to both readers.
|
|
994
|
+
(bind them like any attribute) — an "active" class alone is invisible to both readers. A button that shows and
|
|
995
|
+
hides a panel names it in \`controls\` (\`aria-controls\`, the panel's anchor), and words that change while a
|
|
996
|
+
visitor reads them — a count, a total, a status — sit in a \`container\` with \`live: "polite"\` (\`aria-live\`).
|
|
966
997
|
- **A dropdown opens from a \`button\`** among its children, outside the popup (an avatar, a "⋯": the button holds it and
|
|
967
998
|
has a \`title\`). The dropdown marks it and moves the focus in and out; a box or an icon alone opens nothing from a
|
|
968
999
|
keyboard.
|
|
@@ -37,6 +37,9 @@ type Page = {
|
|
|
37
37
|
value: string;
|
|
38
38
|
}[]) => Promise<void>;
|
|
39
39
|
evaluate: <T>(fn: () => T) => Promise<T>;
|
|
40
|
+
addStyleTag: (options: {
|
|
41
|
+
content: string;
|
|
42
|
+
}) => Promise<unknown>;
|
|
40
43
|
screenshot: (options: Record<string, unknown>) => Promise<Buffer | Uint8Array>;
|
|
41
44
|
/** Playwright's: the page's accessibility tree, already written as an outline. */
|
|
42
45
|
locator?: (selector: string) => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { outlineOfSnapshot, outlineOfTree } from "./accessibilityOutline.js";
|
|
2
2
|
import { PREVIEW_TOKEN_PARAM } from "@plitzi/sdk-server/kernel";
|
|
3
|
+
import { MOTION_STILL_CSS } from "@plitzi/sdk-shared/schema/motion";
|
|
3
4
|
//#region src/modules/mcp/localScreenshotClient.ts
|
|
4
5
|
/**
|
|
5
6
|
* Grow the window to whatever actually scrolls before shooting.
|
|
@@ -90,6 +91,7 @@ var createLocalScreenshotClient = async ({ renderBaseUrl, ignoreHttpsErrors = tr
|
|
|
90
91
|
message: `The page answered ${response.status()}.`
|
|
91
92
|
};
|
|
92
93
|
await page.evaluate(FONTS_READY);
|
|
94
|
+
await page.addStyleTag({ content: MOTION_STILL_CSS });
|
|
93
95
|
if (fullPage) {
|
|
94
96
|
const height = Math.min(await page.evaluate(CONTENT_HEIGHT), MAX_HEIGHT);
|
|
95
97
|
if (height > viewport.height) await setViewport(page, {
|
|
@@ -11,7 +11,7 @@ var explainResource = (uri) => {
|
|
|
11
11
|
names: explainList(kind)
|
|
12
12
|
};
|
|
13
13
|
const explanations = explain(name);
|
|
14
|
-
if (explanations.length === 0) throw new Error(`"${name}" is no element, step, trigger, code or
|
|
14
|
+
if (explanations.length === 0) throw new Error(`"${name}" is no element, step, trigger, code, transformer or helper. List what there is: ${Object.values(EXPLAIN_KINDS).map((plural) => `${PREFIX}${plural}`).join(", ")}.`);
|
|
15
15
|
return {
|
|
16
16
|
name,
|
|
17
17
|
explanations,
|
|
@@ -69,7 +69,7 @@ var createMcpServer = async ({ adapters, getGrant, preview, screenshot, logger,
|
|
|
69
69
|
const getSpace = () => spacePromise ??= loadSpace();
|
|
70
70
|
const server = new McpServer({
|
|
71
71
|
name: "plitzi-mcp",
|
|
72
|
-
version: "0.38.
|
|
72
|
+
version: "0.38.4"
|
|
73
73
|
}, { instructions: hasSpace ? serverInstructions : widgetsOnlyInstructions });
|
|
74
74
|
const { getChanges } = adapters;
|
|
75
75
|
registerResources(server, getSpace, MCP_ENV, log, hasSpace, getChanges ? (query) => getChanges(requireSpaceId(), MCP_ENV, query) : void 0);
|
|
@@ -57,6 +57,7 @@ export declare const applyShape: {
|
|
|
57
57
|
flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
58
58
|
anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
59
59
|
motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
60
|
+
quiet: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
60
61
|
}, z.core.$strip>, z.ZodObject<{
|
|
61
62
|
type: z.ZodLiteral<"deleteElement">;
|
|
62
63
|
pageRef: z.ZodString;
|
|
@@ -53,6 +53,7 @@ export declare const documentOperation: z.ZodDiscriminatedUnion<readonly [z.ZodO
|
|
|
53
53
|
flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
54
54
|
anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
55
55
|
motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
56
|
+
quiet: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
56
57
|
}, z.core.$strip>, z.ZodObject<{
|
|
57
58
|
type: z.ZodLiteral<"deleteElement">;
|
|
58
59
|
pageRef: z.ZodString;
|
|
@@ -838,6 +839,7 @@ export declare const operation: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
838
839
|
flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
839
840
|
anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
840
841
|
motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
842
|
+
quiet: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
841
843
|
}, z.core.$strip>, z.ZodObject<{
|
|
842
844
|
type: z.ZodLiteral<"deleteElement">;
|
|
843
845
|
pageRef: z.ZodString;
|
|
@@ -1895,6 +1897,7 @@ export declare const operations: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject
|
|
|
1895
1897
|
flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1896
1898
|
anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1897
1899
|
motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
1900
|
+
quiet: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
1898
1901
|
}, z.core.$strip>, z.ZodObject<{
|
|
1899
1902
|
type: z.ZodLiteral<"deleteElement">;
|
|
1900
1903
|
pageRef: z.ZodString;
|
|
@@ -2947,6 +2950,7 @@ export declare const documentOperations: z.ZodArray<z.ZodDiscriminatedUnion<read
|
|
|
2947
2950
|
flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2948
2951
|
anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2949
2952
|
motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
2953
|
+
quiet: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
2950
2954
|
}, z.core.$strip>, z.ZodObject<{
|
|
2951
2955
|
type: z.ZodLiteral<"deleteElement">;
|
|
2952
2956
|
pageRef: z.ZodString;
|
|
@@ -25,6 +25,7 @@ export declare const patchElementOp: z.ZodObject<{
|
|
|
25
25
|
flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
26
26
|
anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
27
27
|
motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
28
|
+
quiet: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
28
29
|
}, z.core.$strip>;
|
|
29
30
|
export type PatchElement = z.infer<typeof patchElementOp>;
|
|
30
31
|
export declare const patchElement: (space: Space, env: Env, op: PatchElement) => OpResult;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { findRootByRef, invalidateIndex, resolveRef } from "../../../../helpers/space.js";
|
|
2
2
|
import { pageUri } from "../../../../helpers/uris.js";
|
|
3
3
|
import { empty, fail } from "../../../../helpers/opResult.js";
|
|
4
|
-
import { elementAnchor, elementFlag, elementMotion, elementRuntime, initialStateInput, styleRefs } from "../shared.js";
|
|
4
|
+
import { elementAnchor, elementFlag, elementMotion, elementQuiet, elementRuntime, initialStateInput, styleRefs } from "../shared.js";
|
|
5
5
|
import { guardNewRef, writeInitialState } from "../write.js";
|
|
6
6
|
import { flagGateOf } from "@plitzi/sdk-authoring";
|
|
7
7
|
import { z } from "zod";
|
|
@@ -21,7 +21,8 @@ var patchElementOp = z.object({
|
|
|
21
21
|
runtime: elementRuntime.optional(),
|
|
22
22
|
flag: elementFlag.nullable().optional(),
|
|
23
23
|
anchor: elementAnchor.nullable().optional().describe("null removes it"),
|
|
24
|
-
motion: elementMotion.nullable().optional().describe("null removes it")
|
|
24
|
+
motion: elementMotion.nullable().optional().describe("null removes it"),
|
|
25
|
+
quiet: elementQuiet.nullable().optional()
|
|
25
26
|
}).describe("Partially update an EXISTING element: only the fields you pass change (props/style/initialState are merged, not replaced). Never creates — fails if ref does not resolve. Use upsertElement to create or fully replace.");
|
|
26
27
|
var patchElement = (space, env, op) => {
|
|
27
28
|
const page = findRootByRef(space.schema, op.pageRef);
|
|
@@ -59,6 +60,8 @@ var patchElement = (space, env, op) => {
|
|
|
59
60
|
else if (op.anchor !== void 0) el.definition.anchor = op.anchor;
|
|
60
61
|
if (op.motion === null) Reflect.deleteProperty(el.definition, "motion");
|
|
61
62
|
else if (isMotion(op.motion)) el.definition.motion = op.motion;
|
|
63
|
+
if (op.quiet === null) Reflect.deleteProperty(el.definition, "quiet");
|
|
64
|
+
else if (op.quiet !== void 0) el.definition.quiet = op.quiet;
|
|
62
65
|
return {
|
|
63
66
|
...empty(),
|
|
64
67
|
updated: 1,
|
|
@@ -37,6 +37,7 @@ var upsertElement = (space, env, op) => {
|
|
|
37
37
|
if (op.element.flag !== void 0) existing.definition.flag = flagGateOf(op.element.flag, `Element "${op.element.ref}"`);
|
|
38
38
|
if (op.element.anchor !== void 0) existing.definition.anchor = op.element.anchor;
|
|
39
39
|
if (isMotion(op.element.motion)) existing.definition.motion = op.element.motion;
|
|
40
|
+
if (op.element.quiet !== void 0) existing.definition.quiet = op.element.quiet;
|
|
40
41
|
return {
|
|
41
42
|
...empty(),
|
|
42
43
|
updated: 1,
|
|
@@ -53,6 +53,7 @@ export declare const elementOps: {
|
|
|
53
53
|
flag: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
|
|
54
54
|
anchor: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
|
|
55
55
|
motion: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>>;
|
|
56
|
+
quiet: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodArray<import('zod').ZodString>>>;
|
|
56
57
|
}, import('zod/v4/core').$strip>;
|
|
57
58
|
deleteElement: import('zod').ZodObject<{
|
|
58
59
|
type: import('zod').ZodLiteral<"deleteElement">;
|
|
@@ -22,6 +22,7 @@ export interface ElementInput {
|
|
|
22
22
|
anchor?: string;
|
|
23
23
|
/** Checked by `motionProblems`: what arrives here is one, which `isMotion` narrows it to where it is written. */
|
|
24
24
|
motion?: Record<string, unknown>;
|
|
25
|
+
quiet?: string[];
|
|
25
26
|
children?: ElementInput[];
|
|
26
27
|
}
|
|
27
28
|
export declare const styleRefs: z.ZodObject<{
|
|
@@ -49,6 +50,8 @@ export declare const elementAnchor: z.ZodString;
|
|
|
49
50
|
* refused with the list of right ones, and the guide's Motion section names them all.
|
|
50
51
|
*/
|
|
51
52
|
export declare const elementMotion: z.ZodRecord<z.ZodString, z.ZodUnknown>;
|
|
53
|
+
/** Suggestions' codes an element is not offered, written that way on purpose; never a problem's code. */
|
|
54
|
+
export declare const elementQuiet: z.ZodArray<z.ZodString>;
|
|
52
55
|
export declare const initialStateInput: z.ZodObject<{
|
|
53
56
|
styleVariant: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>>;
|
|
54
57
|
visibility: z.ZodOptional<z.ZodBoolean>;
|
|
@@ -75,6 +78,7 @@ export declare const elementShape: {
|
|
|
75
78
|
flag: z.ZodOptional<z.ZodString>;
|
|
76
79
|
anchor: z.ZodOptional<z.ZodString>;
|
|
77
80
|
motion: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
81
|
+
quiet: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
78
82
|
};
|
|
79
83
|
export declare const elementInput: z.ZodType<ElementInput>;
|
|
80
84
|
export declare const position: z.ZodEnum<{
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { isSuggestionCode } from "@plitzi/sdk-authoring";
|
|
1
2
|
import { z } from "zod";
|
|
2
3
|
import { FLAG_GATE_PATTERN } from "@plitzi/sdk-shared/flags";
|
|
3
4
|
import { ANCHOR_PATTERN } from "@plitzi/sdk-shared/schema/anchor";
|
|
@@ -84,6 +85,13 @@ var elementMotion = z.record(z.string(), z.unknown()).superRefine((motion, ctx)
|
|
|
84
85
|
message: problem
|
|
85
86
|
});
|
|
86
87
|
}).describe("{enter,on,duration,delay,stagger,loop} — guide: Motion");
|
|
88
|
+
/** Suggestions' codes an element is not offered, written that way on purpose; never a problem's code. */
|
|
89
|
+
var elementQuiet = z.array(z.string()).superRefine((codes, ctx) => {
|
|
90
|
+
for (const code of codes.filter((code) => !isSuggestionCode(code))) ctx.addIssue({
|
|
91
|
+
code: "custom",
|
|
92
|
+
message: `"${code}" is no suggestion's code`
|
|
93
|
+
});
|
|
94
|
+
}).describe("Suggestion codes not offered on it, e.g. [\"repeated-shape\"]");
|
|
87
95
|
var initialStateInput = z.object({
|
|
88
96
|
styleVariant: styleVariantInput.optional().describe("Variant each attached class uses: { className: { base|slot: variantName | [names] } }"),
|
|
89
97
|
visibility: z.boolean().optional().describe("Initial visibility of the element")
|
|
@@ -99,7 +107,8 @@ var elementShape = {
|
|
|
99
107
|
runtime: elementRuntime.optional(),
|
|
100
108
|
flag: elementFlag.optional(),
|
|
101
109
|
anchor: elementAnchor.optional(),
|
|
102
|
-
motion: elementMotion.optional()
|
|
110
|
+
motion: elementMotion.optional(),
|
|
111
|
+
quiet: elementQuiet.optional()
|
|
103
112
|
};
|
|
104
113
|
var elementInput = z.lazy(() => z.object({
|
|
105
114
|
...elementShape,
|
|
@@ -156,4 +165,4 @@ var interactionNode = z.object({
|
|
|
156
165
|
preview: z.record(z.string(), z.unknown()).optional()
|
|
157
166
|
});
|
|
158
167
|
//#endregion
|
|
159
|
-
export { bindingCategory, bindingInput, elementAnchor, elementFlag, elementInput, elementMotion, elementRuntime, elementShape, initialStateInput, interactionNode, interactionNodeType, position, ruleGroup, scalar, styleRefs, styleVariantInput };
|
|
168
|
+
export { bindingCategory, bindingInput, elementAnchor, elementFlag, elementInput, elementMotion, elementQuiet, elementRuntime, elementShape, initialStateInput, interactionNode, interactionNodeType, position, ruleGroup, scalar, styleRefs, styleVariantInput };
|
|
@@ -69,7 +69,8 @@ var createElement = (space, page, input, anchorId, drop) => {
|
|
|
69
69
|
...input.runtime === void 0 ? {} : { runtime: input.runtime },
|
|
70
70
|
...input.flag === void 0 ? {} : { flag: flagGateOf(input.flag, `Element "${input.ref}"`) },
|
|
71
71
|
...input.anchor === void 0 ? {} : { anchor: input.anchor },
|
|
72
|
-
...isMotion(input.motion) ? { motion: input.motion } : {}
|
|
72
|
+
...isMotion(input.motion) ? { motion: input.motion } : {},
|
|
73
|
+
...input.quiet === void 0 ? {} : { quiet: input.quiet }
|
|
73
74
|
}
|
|
74
75
|
};
|
|
75
76
|
if (!new FlatMap({ flat: space.schema.flat }).addElement(el, anchorId, drop)) return false;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { actionAccess, actionField, actionLimits, actionNode, actionTriggerParams } from "./actions/document.js";
|
|
2
2
|
import { connectorConnection, readEndpoint, writeEndpoint } from "./connectors/manifest.js";
|
|
3
|
-
import { bindingInput, elementAnchor, elementFlag, elementInput, elementMotion, initialStateInput, interactionNode, position, ruleGroup, styleRefs, styleVariantInput } from "./schema/shared.js";
|
|
3
|
+
import { bindingInput, elementAnchor, elementFlag, elementInput, elementMotion, elementQuiet, initialStateInput, interactionNode, position, ruleGroup, styleRefs, styleVariantInput } from "./schema/shared.js";
|
|
4
4
|
import { ancestors, ancestorsPatch, cssMap, cssPatchMap, definitionSlot, definitionSlotPatch, displayModeCss, displayModeCssPatch, themeValue } from "./style/shared.js";
|
|
5
5
|
import { z } from "zod";
|
|
6
6
|
//#region src/modules/mcp/tools/operations/schemaIds.ts
|
|
@@ -26,6 +26,7 @@ var SHARED_SCHEMAS = [
|
|
|
26
26
|
[elementFlag, "ElementFlag"],
|
|
27
27
|
[elementAnchor, "ElementAnchor"],
|
|
28
28
|
[elementMotion, "ElementMotion"],
|
|
29
|
+
[elementQuiet, "ElementQuiet"],
|
|
29
30
|
[ruleGroup, "RuleGroup"],
|
|
30
31
|
[styleRefs, "StyleRefs"],
|
|
31
32
|
[initialStateInput, "InitialState"],
|
|
@@ -53,6 +53,7 @@ export declare const previewShape: {
|
|
|
53
53
|
flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
54
54
|
anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
55
55
|
motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
56
|
+
quiet: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
56
57
|
}, z.core.$strip>, z.ZodObject<{
|
|
57
58
|
type: z.ZodLiteral<"deleteElement">;
|
|
58
59
|
pageRef: z.ZodString;
|
|
@@ -55,6 +55,7 @@ export declare const renderShape: {
|
|
|
55
55
|
flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
56
56
|
anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
57
57
|
motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
58
|
+
quiet: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
58
59
|
}, z.core.$strip>, z.ZodObject<{
|
|
59
60
|
type: z.ZodLiteral<"deleteElement">;
|
|
60
61
|
pageRef: z.ZodString;
|
|
@@ -53,6 +53,7 @@ export declare const screenshotShape: {
|
|
|
53
53
|
flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
54
54
|
anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
55
55
|
motion: z.ZodOptional<z.ZodNullable<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
|
|
56
|
+
quiet: z.ZodOptional<z.ZodNullable<z.ZodArray<z.ZodString>>>;
|
|
56
57
|
}, z.core.$strip>, z.ZodObject<{
|
|
57
58
|
type: z.ZodLiteral<"deleteElement">;
|
|
58
59
|
pageRef: z.ZodString;
|
|
@@ -54,6 +54,7 @@ export declare const validateShape: {
|
|
|
54
54
|
flag: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
|
|
55
55
|
anchor: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
|
|
56
56
|
motion: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>>;
|
|
57
|
+
quiet: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodArray<import('zod').ZodString>>>;
|
|
57
58
|
}, import('zod/v4/core').$strip>, import('zod').ZodObject<{
|
|
58
59
|
type: import('zod').ZodLiteral<"deleteElement">;
|
|
59
60
|
pageRef: import('zod').ZodString;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plitzi/sdk-mcp",
|
|
3
|
-
"version": "0.38.
|
|
3
|
+
"version": "0.38.4",
|
|
4
4
|
"license": "AGPL-3.0",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -30,14 +30,14 @@
|
|
|
30
30
|
"dependencies": {
|
|
31
31
|
"@modelcontextprotocol/ext-apps": "^1.7.5",
|
|
32
32
|
"@modelcontextprotocol/sdk": "^1.32.0",
|
|
33
|
-
"@plitzi/plitzi-sdk": "0.38.
|
|
34
|
-
"@plitzi/sdk-authoring": "0.38.
|
|
35
|
-
"@plitzi/sdk-elements": "0.38.
|
|
36
|
-
"@plitzi/sdk-interactions": "0.38.
|
|
37
|
-
"@plitzi/sdk-schema": "0.38.
|
|
38
|
-
"@plitzi/sdk-server": "0.38.
|
|
39
|
-
"@plitzi/sdk-shared": "0.38.
|
|
40
|
-
"@plitzi/sdk-style": "0.38.
|
|
33
|
+
"@plitzi/plitzi-sdk": "0.38.4",
|
|
34
|
+
"@plitzi/sdk-authoring": "0.38.4",
|
|
35
|
+
"@plitzi/sdk-elements": "0.38.4",
|
|
36
|
+
"@plitzi/sdk-interactions": "0.38.4",
|
|
37
|
+
"@plitzi/sdk-schema": "0.38.4",
|
|
38
|
+
"@plitzi/sdk-server": "0.38.4",
|
|
39
|
+
"@plitzi/sdk-shared": "0.38.4",
|
|
40
|
+
"@plitzi/sdk-style": "0.38.4",
|
|
41
41
|
"ejs": "^6.0.1",
|
|
42
42
|
"esbuild": "^0.28.2",
|
|
43
43
|
"zod": "^4.6.5"
|