@plitzi/sdk-mcp 0.38.3 → 0.38.5
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 +540 -0
- package/README.md +38 -12
- package/dist/createServer.d.ts +1 -1
- package/dist/createServer.js +1 -1
- package/dist/index.d.ts +3 -4
- package/dist/index.js +1 -4
- package/dist/modules/mcp/apps/render/styles.d.ts +4 -8
- package/dist/modules/mcp/apps/render/styles.js +16 -47
- package/dist/modules/mcp/apps/render/view/index.tsx +1 -1
- package/dist/modules/mcp/catalogs/index.js +2 -2
- package/dist/modules/mcp/catalogs/pluginCatalog.js +2 -2
- package/dist/modules/mcp/e2e/mcpEndpoint.d.ts +2 -1
- package/dist/modules/mcp/handler.d.ts +2 -2
- package/dist/modules/mcp/helpers/callToolResult.d.ts +2 -0
- package/dist/modules/mcp/helpers/callToolResult.js +4 -0
- package/dist/modules/mcp/helpers/guide.js +68 -14
- package/dist/modules/mcp/helpers/index.d.ts +1 -1
- package/dist/modules/mcp/helpers/space.d.ts +4 -1
- package/dist/modules/mcp/helpers/space.js +1 -0
- package/dist/modules/mcp/helpers/uris.d.ts +2 -0
- package/dist/modules/mcp/helpers/uris.js +3 -1
- package/dist/modules/mcp/index.d.ts +1 -1
- package/dist/modules/mcp/localScreenshotClient.d.ts +3 -0
- package/dist/modules/mcp/localScreenshotClient.js +2 -0
- package/dist/modules/mcp/resources/connectors.d.ts +1 -1
- package/dist/modules/mcp/resources/core.js +2 -2
- package/dist/modules/mcp/resources/data.d.ts +8 -0
- package/dist/modules/mcp/resources/data.js +46 -0
- package/dist/modules/mcp/resources/explain.js +1 -1
- package/dist/modules/mcp/resources/primer.js +3 -3
- package/dist/modules/mcp/resources/register.js +12 -2
- package/dist/modules/mcp/resources/renderGuide.js +6 -6
- package/dist/modules/mcp/resources/router.js +3 -1
- package/dist/modules/mcp/resources/schema.js +1 -1
- package/dist/modules/mcp/server.d.ts +3 -3
- package/dist/modules/mcp/server.js +12 -8
- package/dist/modules/mcp/tools/apply/dispatch.js +9 -1
- package/dist/modules/mcp/tools/apply/index.d.ts +12 -2
- package/dist/modules/mcp/tools/apply/index.js +27 -1
- package/dist/modules/mcp/tools/index.d.ts +2 -2
- package/dist/modules/mcp/tools/index.js +2 -2
- package/dist/modules/mcp/tools/operations/connectors/index.d.ts +2 -2
- package/dist/modules/mcp/tools/operations/connectors/manifest.d.ts +1 -1
- package/dist/modules/mcp/tools/operations/connectors/patchConnector.d.ts +1 -1
- package/dist/modules/mcp/tools/operations/connectors/upsertConnector.d.ts +1 -1
- package/dist/modules/mcp/tools/operations/data/data.test.d.ts +1 -0
- package/dist/modules/mcp/tools/operations/data/index.d.ts +32 -0
- package/dist/modules/mcp/tools/operations/data/index.js +54 -0
- package/dist/modules/mcp/tools/operations/index.d.ts +30 -4
- package/dist/modules/mcp/tools/operations/index.js +4 -1
- 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/interactions/patchInteractionNode.d.ts +1 -0
- package/dist/modules/mcp/tools/operations/schema/interactions/upsertInteractionFlow.d.ts +1 -0
- package/dist/modules/mcp/tools/operations/schema/operations.d.ts +3 -0
- package/dist/modules/mcp/tools/operations/schema/shared.d.ts +5 -0
- package/dist/modules/mcp/tools/operations/schema/shared.js +13 -7
- package/dist/modules/mcp/tools/operations/schema/translator.js +1 -1
- package/dist/modules/mcp/tools/operations/schema/write.js +3 -2
- package/dist/modules/mcp/tools/operations/schemaIds.js +3 -3
- package/dist/modules/mcp/tools/operations/style/write.js +1 -1
- package/dist/modules/mcp/tools/preview.d.ts +3 -0
- package/dist/modules/mcp/tools/render.d.ts +3 -0
- package/dist/modules/mcp/tools/screenshot.d.ts +12 -2
- package/dist/modules/mcp/tools/shared/newSuggestions.d.ts +2 -2
- package/dist/modules/mcp/tools/shared/newSuggestions.js +10 -5
- package/dist/modules/mcp/tools/shared/newSuggestions.test.d.ts +1 -0
- package/dist/modules/mcp/tools/shared/tool.d.ts +7 -6
- package/dist/modules/mcp/tools/shared/validator/index.js +2 -2
- package/dist/modules/mcp/tools/tryFunction.js +1 -1
- package/dist/modules/mcp/tools/validate.d.ts +12 -2
- package/dist/modules/mcp/types/appTypes.d.ts +2 -2
- package/dist/modules/mcp/types/toolTypes.d.ts +5 -1
- package/package.json +7 -9
- package/dist/modules/ai/AIEngine.d.ts +0 -20
- package/dist/modules/ai/AIEngine.js +0 -120
- package/dist/modules/ai/index.d.ts +0 -4
- package/dist/modules/ai/toolkit.d.ts +0 -17
- package/dist/modules/ai/toolkit.js +0 -59
- package/dist/modules/mcp/helpers/agentPrompt.d.ts +0 -4
- package/dist/modules/mcp/helpers/agentPrompt.js +0 -123
- /package/dist/modules/{ai/toolkit.test.d.ts → mcp/helpers/callToolResult.test.d.ts} +0 -0
package/README.md
CHANGED
|
@@ -5,10 +5,10 @@ edit a space, the tool engine behind it, the widget renderer, and the draft-prev
|
|
|
5
5
|
|
|
6
6
|
Connecting an agent and what it can do once connected: [AI agents and the MCP server](../../docs/en/mcp.md).
|
|
7
7
|
|
|
8
|
-
It
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
It depends on [`@plitzi/sdk-server`](../server/README.md), never the other way round: that package serves pages,
|
|
9
|
+
this one serves agents. It imports only that package's narrow entries — the HTTP kernel (`/kernel`, the dispatcher
|
|
10
|
+
and the transports), OAuth (`/oauth`) and, for draft preview alone, the renderer (`/ssr`) — so a page-only
|
|
11
|
+
deployment installs none of this and a dedicated MCP server loads no page renderer.
|
|
12
12
|
|
|
13
13
|
## Installation
|
|
14
14
|
|
|
@@ -75,16 +75,42 @@ The server is stateless: it resolves the space per request and reads and writes
|
|
|
75
75
|
| `getOfflineData(spaceId, env, rev)` | for preview | Read side of draft-preview. Only the preview endpoint calls it. |
|
|
76
76
|
| `getComponentCatalog(spaceId, env)` | no | The element types the space's plugins add, for the catalog resources. |
|
|
77
77
|
| `getConnectors` / `saveConnector` / `deleteConnector` | for connectors | The space's connector manifests, read and written by the connector operations. |
|
|
78
|
-
| `getActions` / `getActionTasks` / `saveAction` / `deleteAction` | for actions | The space's server actions, and the catalog of tasks a step may run — the deployment's
|
|
78
|
+
| `getActions` / `getActionTasks` / `saveAction` / `deleteAction` | for actions | The space's server actions, and the catalog of tasks a step may run — the deployment's, the space's own functions and its plugins' server halves, each with its `origin` (`deployment`, `space` or `plugin`). |
|
|
79
79
|
| `getFunctions` / `saveFunctions` / `tryFunction` | for functions | The space's functions: read for `plitzi://functions/{env}`, saved (built and checked, refused from an older copy) by `upsertFunctionFile` / `deleteFunctionFile`, and run by `plitzi_try_function`. |
|
|
80
|
+
| `getData` / `saveData` | for data | The space's data — JSON its server providers read as `/data/<file>`: read for `plitzi://data/{env}`, saved whole (each file checked, refused from an older copy) by `upsertDataFile` / `deleteDataFile`. |
|
|
80
81
|
|
|
81
82
|
Schema and style are read as **separate documents** on purpose: `getOfflineData` is SSR-shaped and strips
|
|
82
83
|
`style.platform`, which the style resources need.
|
|
83
84
|
|
|
85
|
+
`createJsonAdapters({ offlineData })` from `@plitzi/sdk-server` offers `getSchema` and `getStyle` over a
|
|
86
|
+
`{ schema, style }` JSON and — when given a path — `saveSchema` and `saveStyle`, each writing its document back into
|
|
87
|
+
the file, so an MCP can run over it with a `getGrant` of yours beside it. It comes from the package root, which loads
|
|
88
|
+
the page server too; a dedicated MCP that keeps its weight down writes those four itself, as
|
|
89
|
+
[self-hosting/06](../../examples/self-hosting/06-mcp-server) does.
|
|
90
|
+
|
|
84
91
|
Without a `getGrant` that resolves, the server still answers its public surface — the handshake, the tool list,
|
|
85
92
|
the guide, the CSS-property catalog — and asks for a space only when a tool or resource needs one. A grant that
|
|
86
93
|
resolves with `canWrite: false` reads everything and is refused at every write tool.
|
|
87
94
|
|
|
95
|
+
## Options
|
|
96
|
+
|
|
97
|
+
What MCP itself serves is `McpOptions` (`src/options.ts`), the **second** argument — to `createServer` here, and to
|
|
98
|
+
`mcpExtensions(options)` for a page server — never a section of the server config, which a page-only deployment
|
|
99
|
+
types its renderer with.
|
|
100
|
+
|
|
101
|
+
| Option | Default | Purpose |
|
|
102
|
+
|---|---|---|
|
|
103
|
+
| `path` | `/mcp` | Where MCP answers inside a server that also serves pages. A dedicated MCP server owns its whole origin and ignores it. |
|
|
104
|
+
| `renderStreaming` | `true` | Whether the `plitzi_render` view paints from the tool arguments while the host still streams them. `false` keeps the view blank until the finished widget arrives. |
|
|
105
|
+
| `proxy` | off | `McpProxyOptions`: with a `secret`, every external URL a render authored is rewritten to this server's signed endpoint (`path`, default `/__proxy`) and fetched here — the origins a widget needs cannot be declared ahead. `baseUrl`, `maxBytes` (8 MiB), `ttl` (7 days), `tools` (`['plitzi_render']`), `enabled`. |
|
|
106
|
+
| `previewClient` | off | `{ url, secret? }`: the SSR `/preview` endpoint, for an MCP server that runs apart from the renderer. Without it the preview tools report `PREVIEW_UNAVAILABLE`. |
|
|
107
|
+
| `screenshot` | off | `{ serviceUrl, renderBaseUrl }`: the browser service `plitzi_screenshot` renders through, and the SSR base it navigates to. Without it the tool is not registered. |
|
|
108
|
+
| `oauth` | off | OAuth 2.1 for remote connectors — see [OAuth](#oauth). |
|
|
109
|
+
|
|
110
|
+
```ts
|
|
111
|
+
createServer({ adapters }, { screenshot: { serviceUrl, renderBaseUrl }, proxy: { secret } });
|
|
112
|
+
```
|
|
113
|
+
|
|
88
114
|
## Tools
|
|
89
115
|
|
|
90
116
|
| Tool | Access | What it does |
|
|
@@ -98,11 +124,14 @@ resolves with `canWrite: false` reads everything and is refused at every write t
|
|
|
98
124
|
| `plitzi_render` | read | Render a self-contained UI widget, offline, with no space |
|
|
99
125
|
| `plitzi_try_function` | write | Run one task of the space's functions against the draft, in the sandbox: its value, logs and error |
|
|
100
126
|
|
|
127
|
+
The server advertises each tool's access as its `readOnlyHint` annotation, so a host can run a read without asking
|
|
128
|
+
and ask before a write.
|
|
129
|
+
|
|
101
130
|
Reads follow a filesystem model: list cheap, read one item in detail on demand. Agents are told never to
|
|
102
131
|
hand-build a URI — every write and search response hands back the URI to use next.
|
|
103
132
|
|
|
104
133
|
The tool functions are exported directly (`apply`, `search`, `read`, `validate`, `tools`), so a consumer can run
|
|
105
|
-
them in-process
|
|
134
|
+
them in-process instead of speaking MCP over HTTP.
|
|
106
135
|
|
|
107
136
|
## Draft preview
|
|
108
137
|
|
|
@@ -118,16 +147,13 @@ engine's job, not the renderer's.
|
|
|
118
147
|
|
|
119
148
|
## OAuth
|
|
120
149
|
|
|
121
|
-
Opt-in and inert unless configured. With `oauth` set, an unauthenticated JSON-RPC call gets a `401` plus a
|
|
150
|
+
Opt-in and inert unless configured. With `oauth` set (an [option](#options), not part of the server config), an unauthenticated JSON-RPC call gets a `401` plus a
|
|
122
151
|
`WWW-Authenticate` challenge pointing at the discovery document — which is what makes a host such as Claude
|
|
123
152
|
Desktop start the flow. Without it, the server stays anonymous, discovery answers `404`, and every caller reaches
|
|
124
153
|
the public surface.
|
|
125
154
|
|
|
126
155
|
```ts
|
|
127
|
-
createServer({
|
|
128
|
-
adapters,
|
|
129
|
-
oauth: { adapters: oauthAdapters, issuer, guest: { target: widgetsOnlyTarget } }
|
|
130
|
-
});
|
|
156
|
+
createServer({ adapters }, { oauth: { adapters: oauthAdapters, issuer, guest: { target: widgetsOnlyTarget } } });
|
|
131
157
|
```
|
|
132
158
|
|
|
133
159
|
Publish the connector URL **with a path** (`https://host/mcp`), not the bare origin.
|
|
@@ -177,7 +203,7 @@ MCP server, [self-hosting/07](../../examples/self-hosting/07-ssr-preview) is the
|
|
|
177
203
|
| Import | Carries |
|
|
178
204
|
|---|---|
|
|
179
205
|
| `@plitzi/sdk-mcp/server` | The dedicated MCP server and its clients. What an MCP deployment wires. |
|
|
180
|
-
| `@plitzi/sdk-mcp` | Everything above plus the pipeline stages, `createPreview
|
|
206
|
+
| `@plitzi/sdk-mcp` | Everything above plus the pipeline stages, `createPreview` and the tool engine. |
|
|
181
207
|
|
|
182
208
|
The split is about weight, not taste: ESM re-exports load eagerly, so the barrel pulls the draft-preview path and
|
|
183
209
|
the renderer it reaches into. A `no-restricted-imports` rule and a test in `src/packageBoundary.test.ts` keep this
|
package/dist/createServer.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { McpOptions } from './options';
|
|
2
2
|
import { SSRServer, SSRServerConfig } from '@plitzi/sdk-shared';
|
|
3
|
-
/** The server this package makes: the lean
|
|
3
|
+
/** The server this package makes: the lean MCP pipeline over the bare context — no render template, caches
|
|
4
4
|
* or plugin manager. `config` is the HTTP server's (port, TLS, health, logger, adapters); `options` is what MCP
|
|
5
5
|
* itself serves, and lives here rather than in that config because the server does not need to know. Pair it with
|
|
6
6
|
* the MCP adapters (getGrant + getSchema/getStyle/saveSchema/saveStyle) — the page adapters are not required, and
|
package/dist/createServer.js
CHANGED
|
@@ -5,7 +5,7 @@ var noPlugins = {
|
|
|
5
5
|
register: () => void 0,
|
|
6
6
|
invalidate: () => Promise.resolve()
|
|
7
7
|
};
|
|
8
|
-
/** The server this package makes: the lean
|
|
8
|
+
/** The server this package makes: the lean MCP pipeline over the bare context — no render template, caches
|
|
9
9
|
* or plugin manager. `config` is the HTTP server's (port, TLS, health, logger, adapters); `options` is what MCP
|
|
10
10
|
* itself serves, and lives here rather than in that config because the server does not need to know. Pair it with
|
|
11
11
|
* the MCP adapters (getGrant + getSchema/getStyle/saveSchema/saveStyle) — the page adapters are not required, and
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
/** Everything this package offers: the MCP server, the tool engine that backs it, the
|
|
2
|
-
*
|
|
1
|
+
/** Everything this package offers: the MCP server, the tool engine that backs it, and the stages that mount all of
|
|
2
|
+
* it inside somebody else's page server.
|
|
3
3
|
*
|
|
4
4
|
* A dedicated MCP deployment wants `@plitzi/sdk-mcp/server` instead — this barrel also pulls the draft-preview
|
|
5
5
|
* endpoint, which reaches into the SSR renderer. */
|
|
@@ -10,8 +10,7 @@ export { createOAuthGuardStage, createOAuthStage } from '@plitzi/sdk-server/oaut
|
|
|
10
10
|
export { previewStage } from './stages/preview';
|
|
11
11
|
export { createWidgetProxyStage } from './stages/proxy';
|
|
12
12
|
export { createPreview } from './preview/createPreview';
|
|
13
|
-
export {
|
|
14
|
-
export { createMcpServer, handleMcp, serveMcp, readMcpBody, buildAgentGuide, createHttpPreviewClient, createHttpScreenshotClient, createLocalScreenshotClient, resolveLocalBrowser, outlineOfSnapshot, outlineOfTree, unnamedControls } from './modules/mcp';
|
|
13
|
+
export { createMcpServer, handleMcp, serveMcp, readMcpBody, createHttpPreviewClient, createHttpScreenshotClient, createLocalScreenshotClient, resolveLocalBrowser, outlineOfSnapshot, outlineOfTree, unnamedControls } from './modules/mcp';
|
|
15
14
|
export { apply, search, read, validate, applyShape, searchShape, readShape, validateShape, operation, tools } from './modules/mcp/tools';
|
|
16
15
|
export type { McpServerContext, McpRequestOptions, PreviewClient, PreviewRequestBody, PreviewResult, HttpPreviewClientConfig, ScreenshotClient, ScreenshotImage, ScreenshotResult, AccessibilityNode, AccessibilityOutline, CaptureView, UnnamedControl, Viewport, HttpScreenshotClientConfig } from './modules/mcp';
|
|
17
16
|
export type { ApplyInput, SearchInput, SearchResponse, SearchHit, ReadInput, ReadResponse, ReadHit, ValidateInput, WriteResponse, WriteElement, Persisters, Operation, ToolDef, ToolContext } from './modules/mcp/tools';
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { buildAgentGuide } from "./modules/mcp/helpers/agentPrompt.js";
|
|
2
1
|
import { operation } from "./modules/mcp/tools/operations/index.js";
|
|
3
2
|
import { apply, applyShape } from "./modules/mcp/tools/apply/index.js";
|
|
4
3
|
import { read, readShape } from "./modules/mcp/tools/read.js";
|
|
@@ -6,7 +5,6 @@ import { outlineOfSnapshot, outlineOfTree, unnamedControls } from "./modules/mcp
|
|
|
6
5
|
import { search, searchShape } from "./modules/mcp/tools/search.js";
|
|
7
6
|
import { validate, validateShape } from "./modules/mcp/tools/validate.js";
|
|
8
7
|
import { tools } from "./modules/mcp/tools/index.js";
|
|
9
|
-
import { bindTools, getAllowedModes, isCallToolResult, isToolActive, resolveToolHandler, toolResponseErr, toolResponseFromResult, toolResponseOk, zodToJsonSchema } from "./modules/ai/toolkit.js";
|
|
10
8
|
import { createMcpServer } from "./modules/mcp/server.js";
|
|
11
9
|
import { handleMcp, readMcpBody, serveMcp } from "./modules/mcp/handler.js";
|
|
12
10
|
import { createHttpPreviewClient } from "./modules/mcp/previewClient.js";
|
|
@@ -17,7 +15,6 @@ import { previewStage } from "./stages/preview.js";
|
|
|
17
15
|
import { createWidgetProxyStage } from "./stages/proxy.js";
|
|
18
16
|
import { buildMCPPipeline, mcpExtensions } from "./pipeline.js";
|
|
19
17
|
import { createServer } from "./createServer.js";
|
|
20
|
-
import AIEngine from "./modules/ai/AIEngine.js";
|
|
21
18
|
import { createLocalScreenshotClient, resolveLocalBrowser } from "./modules/mcp/localScreenshotClient.js";
|
|
22
19
|
import { createOAuthGuardStage, createOAuthStage } from "@plitzi/sdk-server/oauth";
|
|
23
|
-
export {
|
|
20
|
+
export { apply, applyShape, buildMCPPipeline, createHttpPreviewClient, createHttpScreenshotClient, createLocalScreenshotClient, createMcpOnlyStage, createMcpServer, createMcpStage, createOAuthGuardStage, createOAuthStage, createPreview, createServer, createWidgetProxyStage, handleMcp, mcpExtensions, operation, outlineOfSnapshot, outlineOfTree, previewStage, read, readMcpBody, readShape, resolveLocalBrowser, search, searchShape, serveMcp, tools, unnamedControls, validate, validateShape };
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
/**
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
base: string;
|
|
5
|
-
fonts: string;
|
|
6
|
-
};
|
|
7
|
-
/** What the page shell inlines: the SDK stylesheet without the icon fonts. */
|
|
1
|
+
/** The icon sheet with each font it names inlined: the widget's sandbox reaches no origin to fetch one from. */
|
|
2
|
+
export declare const inlineIconFonts: (css: string, readFont: (file: string) => Buffer) => string;
|
|
3
|
+
/** What the page shell inlines. */
|
|
8
4
|
export declare const widgetCss: () => string;
|
|
9
|
-
/**
|
|
5
|
+
/** Font Awesome, fonts and all, for the renders that draw an icon. */
|
|
10
6
|
export declare const iconFontCss: () => string;
|
|
@@ -2,53 +2,22 @@ import { require } from "../shared/resolve.js";
|
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { readFileSync } from "node:fs";
|
|
4
4
|
//#region src/modules/mcp/apps/render/styles.ts
|
|
5
|
-
/** The SDK
|
|
5
|
+
/** The SDK's stylesheets, as a widget gets them.
|
|
6
6
|
*
|
|
7
7
|
* Everything the page shell inlines is paid for by EVERY widget: the host loads the ui:// page into a fresh
|
|
8
|
-
* sandboxed iframe and parses it whole before anything paints, which is the "Rendering…" the user waits through.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
var
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
if (depth === 0) return at + 1;
|
|
23
|
-
}
|
|
24
|
-
return css.length;
|
|
25
|
-
};
|
|
26
|
-
/** Lifts every @font-face block out of a stylesheet. Brace counting rather than a CSS parser: a @font-face body is
|
|
27
|
-
* plain declarations, and base64 payloads and url() values carry no braces of their own. */
|
|
28
|
-
var splitFontFaces = (css) => {
|
|
29
|
-
const base = [];
|
|
30
|
-
const fonts = [];
|
|
31
|
-
let cursor = 0;
|
|
32
|
-
for (let at = css.indexOf("@font-face", cursor); at !== -1; at = css.indexOf("@font-face", cursor)) {
|
|
33
|
-
const open = css.indexOf("{", at);
|
|
34
|
-
if (open === -1) break;
|
|
35
|
-
const end = blockEnd(css, open);
|
|
36
|
-
base.push(css.slice(cursor, at));
|
|
37
|
-
fonts.push(css.slice(at, end));
|
|
38
|
-
cursor = end;
|
|
39
|
-
}
|
|
40
|
-
base.push(css.slice(cursor));
|
|
41
|
-
return {
|
|
42
|
-
base: base.join(""),
|
|
43
|
-
fonts: fonts.join("")
|
|
44
|
-
};
|
|
45
|
-
};
|
|
46
|
-
var stylesheet = () => readFileSync(path.join(path.dirname(require.resolve("@plitzi/plitzi-sdk")), "plitzi-sdk.css"), "utf-8");
|
|
47
|
-
var split;
|
|
48
|
-
var sdkStyles = () => split ??= splitFontFaces(stylesheet());
|
|
49
|
-
/** What the page shell inlines: the SDK stylesheet without the icon fonts. */
|
|
50
|
-
var widgetCss = () => sdkStyles().base;
|
|
51
|
-
/** The icon fonts, for the renders that draw one. */
|
|
52
|
-
var iconFontCss = () => sdkStyles().fonts;
|
|
8
|
+
* sandboxed iframe and parses it whole before anything paints, which is the "Rendering…" the user waits through. So
|
|
9
|
+
* the shell takes only `plitzi-sdk.css`, and Font Awesome — its rules in `plitzi-sdk-icons.css`, its fonts files
|
|
10
|
+
* beside it — travels in the tool result of the renders that actually draw an icon (see tools/render.ts). A widget
|
|
11
|
+
* without icons never downloads a glyph. */
|
|
12
|
+
var sdkDist = () => path.dirname(require.resolve("@plitzi/plitzi-sdk"));
|
|
13
|
+
var FONT_URL = /url\((webfonts\/[\w.-]+\.woff2)\)/g;
|
|
14
|
+
/** The icon sheet with each font it names inlined: the widget's sandbox reaches no origin to fetch one from. */
|
|
15
|
+
var inlineIconFonts = (css, readFont) => css.replace(FONT_URL, (_match, file) => `url(data:font/woff2;base64,${readFont(file).toString("base64")})`);
|
|
16
|
+
var base;
|
|
17
|
+
var icons;
|
|
18
|
+
/** What the page shell inlines. */
|
|
19
|
+
var widgetCss = () => base ??= readFileSync(path.join(sdkDist(), "plitzi-sdk.css"), "utf-8");
|
|
20
|
+
/** Font Awesome, fonts and all, for the renders that draw an icon. */
|
|
21
|
+
var iconFontCss = () => icons ??= inlineIconFonts(readFileSync(path.join(sdkDist(), "plitzi-sdk-icons.css"), "utf-8"), (file) => readFileSync(path.join(sdkDist(), file)));
|
|
53
22
|
//#endregion
|
|
54
|
-
export { iconFontCss,
|
|
23
|
+
export { iconFontCss, inlineIconFonts, widgetCss };
|
|
@@ -34,7 +34,7 @@ const ErrorPanel = ({ title, details }: { title: string; details: string }) => (
|
|
|
34
34
|
* wholesale when the result lands. A host that streams nothing paints none of this and keeps the static text. */
|
|
35
35
|
const SKELETON_BAR_WIDTHS = ['92%', '78%', '85%', '64%', '88%', '72%'];
|
|
36
36
|
|
|
37
|
-
// The deployment's own switch (
|
|
37
|
+
// The deployment's own switch (McpOptions.renderStreaming), handed over by the page. Absent means on: a page built
|
|
38
38
|
// before the setting existed carries none, and a host that streams no arguments paints the same either way.
|
|
39
39
|
const streamingEnabled =
|
|
40
40
|
(globalThis as { __PLITZI_VIEW__?: { streaming?: boolean } }).__PLITZI_VIEW__?.streaming !== false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { buildDataSourceCatalog, buildInteractionCatalog, observedDataSources, observedInteractionActions } from "./observed.js";
|
|
2
2
|
import { buildTypeRegistry } from "./registry.js";
|
|
3
|
-
import {
|
|
4
|
-
export {
|
|
3
|
+
import { applyBuiltinCallback, applyElementCallback, applyUtility, cssProperties as cssProperties$1, cssShorthands, elementCatalog as elementCatalog$1, elementTypeNames, expandShorthand, expandShorthandPatch, getElementCallback, getGlobalCallback, getUtility, hiddenParams, isCssProperty, reconcileParams, suggestCssProperty } from "@plitzi/sdk-authoring";
|
|
4
|
+
export { applyBuiltinCallback, applyElementCallback, applyUtility, buildDataSourceCatalog, buildInteractionCatalog, buildTypeRegistry, cssProperties$1 as cssProperties, cssShorthands, elementCatalog$1 as elementCatalog, elementTypeNames, expandShorthand, expandShorthandPatch, getElementCallback, getGlobalCallback, getUtility, hiddenParams, isCssProperty, observedDataSources, observedInteractionActions, reconcileParams, suggestCssProperty };
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*
|
|
11
11
|
* The BUILT-IN types are not here: their structural half (attributes, style selectors, default styles) comes from
|
|
12
12
|
* `@plitzi/sdk-elements`, which this package deliberately does not depend on — a React element library is the
|
|
13
|
-
* heaviest possible import for a server that renders nothing. Deployments merge those in themselves;
|
|
14
|
-
*
|
|
13
|
+
* heaviest possible import for a server that renders nothing. Deployments merge those in themselves; what each one is
|
|
14
|
+
* for is `elementCatalog`, read off the declarations by `@plitzi/sdk-authoring`.
|
|
15
15
|
*/
|
|
16
16
|
var MANIFEST_TTL_MS = 6e5;
|
|
17
17
|
var manifestCache = /* @__PURE__ */ new Map();
|
|
@@ -18,7 +18,8 @@ export interface McpEndpointOptions {
|
|
|
18
18
|
/** Attach a space to the connection, the way an authorized connector's token does — the server then offers its
|
|
19
19
|
* editing surface. Omitted, the endpoint is the guest one: no space, so only what works without one. */
|
|
20
20
|
spaceId?: number;
|
|
21
|
-
/** The deployment switch a consumer sets as `
|
|
21
|
+
/** The deployment switch a consumer sets as `McpOptions.renderStreaming`. Omitted, the server's own default
|
|
22
|
+
* stands. */
|
|
22
23
|
renderStreaming?: boolean;
|
|
23
24
|
}
|
|
24
25
|
/** Start the endpoint and connect a real MCP client to it, as a remote connector does. */
|
|
@@ -10,9 +10,9 @@ export type McpRequestOptions = {
|
|
|
10
10
|
preview?: PreviewClient;
|
|
11
11
|
screenshot?: ScreenshotClient;
|
|
12
12
|
logger?: ServerLogger;
|
|
13
|
-
/** Deployment switch for the plitzi_render view (see `
|
|
13
|
+
/** Deployment switch for the plitzi_render view (see `McpOptions.renderStreaming`). Defaults to true. */
|
|
14
14
|
renderStreaming?: boolean;
|
|
15
|
-
/** Where a rendered widget loads everything external from (see `
|
|
15
|
+
/** Where a rendered widget loads everything external from (see `McpOptions.proxy`). Absent → the URLs an agent
|
|
16
16
|
* authored travel to the host exactly as written. */
|
|
17
17
|
proxy?: ResourceProxy;
|
|
18
18
|
};
|
|
@@ -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(", ");
|
|
@@ -61,7 +61,8 @@ computed for you). Node types: \`callback\` (an element's own callback — \`ele
|
|
|
61
61
|
(category/key/value/revertOnFinish) ≠ global \`setState\` (source \`state\`, key/type/value). To turn a step off use
|
|
62
62
|
\`patchInteractionNode {enabled:false}\` — \`deleteInteraction\` removes it (destructive; confirm first). Any param
|
|
63
63
|
**value** can be a binding token \`{{ source }}\` (e.g. notification \`content: "{{ list_<name>.item.name }}"\`).
|
|
64
|
-
Steps read the page as it is when they run; a refiring trigger is ignored unless \`whileRunning: "queue"
|
|
64
|
+
Steps read the page as it is when they run; a refiring trigger is ignored unless \`whileRunning: "queue"\` (or
|
|
65
|
+
\`"latest"\`: the newest firing stops the running one); keyboard
|
|
65
66
|
shortcuts are the \`onKey\` trigger (\`keys: "shift+f, escape"\`).
|
|
66
67
|
|
|
67
68
|
**CMS / API integrations** (\`upsertConnector\`): a **connector** is a manifest declaring a provider's base URL,
|
|
@@ -88,6 +89,12 @@ button/link needs words (an icon-only button a \`title\`), every field a \`label
|
|
|
88
89
|
image an \`alt\` or \`decorative: true\`; clicks go on a \`button\`/\`link\`, never a container; headings step down one
|
|
89
90
|
level at a time. \`plitzi_screenshot view:"accessibility"\` shows the tree and what has no name.
|
|
90
91
|
|
|
92
|
+
**Everything the space holds is public.** Its pages, variables, attributes, flow params and mock data ship to every
|
|
93
|
+
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
|
|
94
|
+
data only some visitors may read never goes in any of them: a secret is a credential the owner attaches (a connector, an
|
|
95
|
+
action or a function names it, never carries it), and data for some visitors only comes from a \`runtime: "server"\`
|
|
96
|
+
provider or an action that checks who is asking.
|
|
97
|
+
|
|
91
98
|
**Touched elements must be malformation-free.** Editing an element also checks its CURRENT stored content and BLOCKS
|
|
92
99
|
the save on any \`Pre-existing malformation in element …\` error (a broken transformer, a malformed step, an attribute
|
|
93
100
|
it never reads) — even parts you did not touch. These are NOT from your change (the message says so); fix them in the
|
|
@@ -172,6 +179,8 @@ Never download a whole tree you do not need.
|
|
|
172
179
|
action may be built from.
|
|
173
180
|
- \`plitzi://functions/{env}\` — the space's **functions**, its own server code: which files, and the tasks, routes and
|
|
174
181
|
hosts they declare. \`plitzi://functions/{env}/{+path}\` reads one file whole. See *Functions* below.
|
|
182
|
+
- \`plitzi://data/{env}\` — the space's **data**: JSON files its server providers read, never served.
|
|
183
|
+
\`plitzi://data/{env}/{+path}\` reads one, parsed. See *Data* below.
|
|
175
184
|
- \`plitzi://changes/{env}\` — the space's **change history**, read-only and newest first: who made each change (a
|
|
176
185
|
person in the builder, an agent, the autofix), when, and every element, class, token or font it touched, whole, before
|
|
177
186
|
and after. \`/{id}\` for the history of one of them — how you find what changed an element you are asked about, or
|
|
@@ -234,7 +243,8 @@ space already had is not repeated on every batch — and none of them blocks any
|
|
|
234
243
|
page being shown: the \`current\` state marks it (see *Pages & folders*).
|
|
235
244
|
- \`repeated-shape\` — one structure written again with other words: a **component** with props
|
|
236
245
|
(\`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
|
|
246
|
+
A few cards a person rewords by hand can stay cards; siblings that read different data or keep different state are
|
|
247
|
+
controls written alike, and are not offered.
|
|
238
248
|
- \`content-attribute\` — a \`button\` or \`link\` whose children are only a \`text\` and/or a \`fontAwesome\`: its words
|
|
239
249
|
are its own \`content\` and the icon its \`icon\`. What the text's class adds (\`white-space: nowrap\`) moves to the
|
|
240
250
|
box's class — never the class itself; the icon's class goes in the \`icon\` slot.
|
|
@@ -242,7 +252,14 @@ space already had is not repeated on every batch — and none of them blocks any
|
|
|
242
252
|
\`states\`/\`ancestors\`, the SDK (reduced motion, the theme toggle's icons) or the space's notification look says.
|
|
243
253
|
- \`heavy-animation\` — keyframes that animate a size, a position, a blur, a shadow, or a colour in a loop: they stutter
|
|
244
254
|
while the page loads. Lighter, not shorter — see **Motion — good practices**.
|
|
245
|
-
\`
|
|
255
|
+
- \`unused-class\`, \`unused-token\`, \`unused-component\` — declared and read by nothing: remove it
|
|
256
|
+
(\`deleteDefinition\`, \`deleteStyleVariable\`, \`deleteComponent\`), or use it where it was meant to go. Said
|
|
257
|
+
when a batch leaves one behind.
|
|
258
|
+
- \`literal-colour\` — a class painted from the palette typing out a token's light value: \`var(--token)\` when it
|
|
259
|
+
should follow the scheme; a token of one value when it must stay the same in both.
|
|
260
|
+
\`plitzi://explain/<code>\` explains each. Take one unless the copies are about to diverge; one left on purpose is
|
|
261
|
+
quieted on an element it names — \`quiet: ["repeated-shape"]\` on \`upsertElement\`/\`patchElement\` (\`null\` removes it)
|
|
262
|
+
— and is not offered again, here, in the builder or in authoring. Suggestions' codes only.
|
|
246
263
|
|
|
247
264
|
## Readers: resources vs plitzi_search vs plitzi_read (do not confuse them)
|
|
248
265
|
Three ways to read, each for a different moment — pick by what you have in hand:
|
|
@@ -269,7 +286,7 @@ runtime wires by it — there is no second key and nothing to translate. Creatin
|
|
|
269
286
|
That name is the **wiring key**: a provider registers its data source as \`<type>_<name>\`, so a \`source\` you write
|
|
270
287
|
against a name resolves to that element at runtime. Rules for a **new** name (both enforced; a violation fails the
|
|
271
288
|
batch):
|
|
272
|
-
- Charset \`[A-Za-z0-9_-]\`, **starting with a letter** (e.g. \`"products-api"\`, \`"food_item"\`). A \`.\` would split
|
|
289
|
+
- Charset \`[A-Za-z0-9_-]\`, **starting with a letter** and not ending in \`-\` (e.g. \`"products-api"\`, \`"food_item"\`). A \`.\` would split
|
|
273
290
|
the \`<type>_<name>.<field>\` source path and the interaction target lookup, so **no dots**. An **underscore is
|
|
274
291
|
allowed**: the FIRST \`_\` separates \`<type>\` from the name and element types are camelCase with none, so
|
|
275
292
|
underscores inside a name are unambiguous (\`list_food_item\` → type \`list\`, name \`food_item\`).
|
|
@@ -281,7 +298,8 @@ batch):
|
|
|
281
298
|
**Where an element renders** is its \`runtime\`, settable on \`upsertElement\`/\`patchElement\`: \`"shared"\` (the
|
|
282
299
|
default, both sides), \`"client"\` (browser only) or \`"server"\` (SSR only). It matters for one thing above all — an
|
|
283
300
|
\`apiContainer\` reads through a **connector** only when it is \`"server"\` (see *Connectors*). An element read
|
|
284
|
-
reports it only when it is set.
|
|
301
|
+
reports it only when it is set. The page server resolves \`"server"\` elements of a page and its layouts only, never
|
|
302
|
+
inside a component — one there is refused; put the provider on the page and hand the component its rows as a prop.
|
|
285
303
|
|
|
286
304
|
**Renaming** (\`patchElement\` with \`rename\`) moves the one key: the parent's child list, every binding source and
|
|
287
305
|
every interaction target across the space that named the old one is repointed with it, so nothing comes unwired.
|
|
@@ -412,7 +430,10 @@ provider's records into a list element:
|
|
|
412
430
|
**What an \`apiContainer\` publishes** depends on where it reads. Through a connector (\`runtime: "server"\`) it is the
|
|
413
431
|
fixed shape under *Connectors* — \`.records\` or \`.record\`, \`.pageInfo\`, … With a browser \`query\` it is the
|
|
414
432
|
response: \`.data\` (the parsed body — an API answering \`{ "items": [...] }\` is read as
|
|
415
|
-
\`apiContainer_<name>.data.items\`) and \`.status\` (the HTTP status)
|
|
433
|
+
\`apiContainer_<name>.data.items\`) and \`.status\` (the HTTP status) — and a \`"server"\` provider with only a
|
|
434
|
+
\`query\` (a JSON file the deployment serves) answers in that same shape, so moving it to the server changes no
|
|
435
|
+
binding. Fed by a server **action**, it is the action's output at the root (\`apiContainer_<name>.items\`, never
|
|
436
|
+
\`.data.items\`). All add \`.isLoading\` (true while asked again too), \`.isEmpty\`,
|
|
416
437
|
\`.hasError\` and \`.errorMessage\`.
|
|
417
438
|
|
|
418
439
|
**Source scope — a source is visible to the provider's DESCENDANTS only.** An element source named
|
|
@@ -435,7 +456,7 @@ the API needs a token or the content should be in the HTML), or a browser-side \
|
|
|
435
456
|
\`{ action, params }\`; the runtime runs them in order and resolves each by its \`action\` alone, so an **unknown
|
|
436
457
|
action is silently skipped** and the raw value passes through. Use the **exact** action names from
|
|
437
458
|
\`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 —
|
|
459
|
+
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
460
|
show a number with units:
|
|
440
461
|
\`{ "type": "upsertBinding", "pageRef": "home", "ref": "food-item-time", "category": "attributes",
|
|
441
462
|
"binding": { "to": "content", "source": "list_food-list.item.cookTimeMinutes",
|
|
@@ -459,7 +480,8 @@ you — never wire them by hand. Each step also has an \`enabled\` flag (see dis
|
|
|
459
480
|
**Each step reads the page as it is when it runs**: a \`when\` or a \`{{ state.x }}\` after a \`setState\` sees the new
|
|
460
481
|
value, and one after a \`delay\` sees what changed meanwhile. To act on the value from BEFORE a write, put the reading
|
|
461
482
|
step first. **A trigger fired again while its flow runs is ignored** (no double submit); set \`"whileRunning": "queue"\`
|
|
462
|
-
on the trigger node for a stream of events that must each run in order (\`"parallel"\` runs them at once
|
|
483
|
+
on the trigger node for a stream of events that must each run in order (\`"parallel"\` runs them at once,
|
|
484
|
+
\`"latest"\` stops the running flow — its server action or request too — for a search as you type).
|
|
463
485
|
**Keyboard shortcuts** are a trigger every element has: \`onKey\` with param \`keys\` — \`"f"\`, \`"shift+f"\`,
|
|
464
486
|
\`"mod+k"\` (⌘ on a Mac, Ctrl elsewhere), \`"plus, ="\`, \`"escape"\`. Heard on the whole page while the element is
|
|
465
487
|
mounted, ignored while someone types in a field; the flow reads the key pressed as \`{{ <trigger id>.key }}\`.
|
|
@@ -538,6 +560,20 @@ Discover valid actions in \`plitzi://interactions/{env}\`: \`actions\` = observe
|
|
|
538
560
|
node type and valid params per action. An element read lists its flows as ordered nodes (each with its \`id\` and
|
|
539
561
|
\`enabled\`), so a follow-up patch/delete needs no extra read.
|
|
540
562
|
|
|
563
|
+
## What is public — and where a secret goes
|
|
564
|
+
A space is served to anyone who opens it, and everything it is made of goes with it:
|
|
565
|
+
|
|
566
|
+
- **The documents.** Every page, layout and component, every schema and style variable, every attribute, binding,
|
|
567
|
+
flow param and \`mockData\` reaches the visitor's browser with the page. Hiding an element (\`visible: false\`, a
|
|
568
|
+
flag, a condition) does not remove it from what is sent.
|
|
569
|
+
- **The files.** A file on one of the space's public buckets is on the internet at its address, signed in or not —
|
|
570
|
+
for pictures, fonts and data every visitor may see.
|
|
571
|
+
|
|
572
|
+
So a secret — an API key, a token, a password — never goes in a document or a public file. It is a **credential**,
|
|
573
|
+
created by the space owner in the builder, which a connector, an action or a function **names** and never carries.
|
|
574
|
+
Data only some visitors may read comes from a \`runtime: "server"\` provider or a server action whose \`access\` checks
|
|
575
|
+
who is asking — never from a public file or a document the page filters on the client.
|
|
576
|
+
|
|
541
577
|
## Connectors — CMS and API integrations
|
|
542
578
|
A **connector** is how a space reads real content from Strapi, WordPress, Contentful, Directus or any REST service.
|
|
543
579
|
It is **a manifest, not code**: you declare the base URL, the endpoints, the auth template and the filter operators,
|
|
@@ -647,7 +683,7 @@ returns **no records** rather than the whole collection — a URL that addressed
|
|
|
647
683
|
**Paging** is the \`pagination\` prop: \`"none"\`, \`"url"\` (the page number rides the query string, so pages are
|
|
648
684
|
shareable and indexable — prefer it) or \`"append"\` (a "load more" list). Give each list on a page its own
|
|
649
685
|
\`pageParam\` so two lists page independently. The provider also offers the \`loadMore\` and \`goToPage\` callbacks to
|
|
650
|
-
interaction flows, and \`
|
|
686
|
+
interaction flows, \`performQuery\` to refetch, and \`cancelQuery\` to drop a request in flight (a STOP).
|
|
651
687
|
|
|
652
688
|
**Writing back** (a form, a "delete" button): declare the endpoint under \`endpoints.write\`, then call the provider's
|
|
653
689
|
**\`writeRecord\`** callback from an interaction flow — nodeType \`callback\`, \`elementId\` the apiContainer's ref,
|
|
@@ -706,6 +742,19 @@ any other (\`<namespace>.<action>\`), listed in \`plitzi://actions/{env}/tasks\`
|
|
|
706
742
|
The live site runs what the space was last published with, never the draft. Running functions is part of the paid
|
|
707
743
|
plans: on another plan they save, and a run answers why it did not start — tell the user rather than work around it.
|
|
708
744
|
|
|
745
|
+
## Data
|
|
746
|
+
JSON the space's pages read on the server and never serve — a catalog, prices, a menu: what a page needs whole and
|
|
747
|
+
nobody edits element by element.
|
|
748
|
+
|
|
749
|
+
- **Read** it as a provider does: \`apiContainer\` with \`runtime: "server"\` and \`query: "/data/products.json"\` reads
|
|
750
|
+
\`products.json\` of \`plitzi://data/{env}\`, and the page arrives with it. A browser provider reading \`/data/…\` is
|
|
751
|
+
refused — the data is the server's.
|
|
752
|
+
- **Write** it with \`upsertDataFile { path, content }\` (the whole file, as JSON text; \`deleteDataFile { path }\`
|
|
753
|
+
removes one): a path of plain segments ending in \`.json\`. Saved whole, with the batch: a newer copy (somebody saved
|
|
754
|
+
since you read it) refuses it — read it again.
|
|
755
|
+
- **What a provider reads is in the page it renders**: data a page must not carry belongs in a server action, which
|
|
756
|
+
answers only what is shown. The live site reads what the space was last published with, never the draft.
|
|
757
|
+
|
|
709
758
|
## Realtime channels
|
|
710
759
|
Pages that see each other — cursors, presence, a shared board, a game. Three parts, all needed:
|
|
711
760
|
|
|
@@ -926,8 +975,10 @@ Space-level configuration lives in \`plitzi://settings/{env}\` and is edited wit
|
|
|
926
975
|
## Motion — good practices
|
|
927
976
|
A preset first: an element's \`motion\` field (\`upsertElement\`/\`patchElement\`) —
|
|
928
977
|
\`{ "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
|
-
|
|
978
|
+
played by the SDK, cheap and stilled for reduced motion. \`on\`: \`load\` (default), \`view\` (once, the first time it
|
|
979
|
+
comes into view, then it stays) or \`scroll\` (follows the scroll both ways — it fades back out as the reader scrolls
|
|
980
|
+
up past it; only for an effect that is about the scroll itself). Enters: ${MOTION_ENTERS.join(", ")}; loops:
|
|
981
|
+
${MOTION_LOOPS.join(", ")}. Beyond them, keyframes go in \`customCss\` (\`patchSettings\`), a
|
|
931
982
|
definition names them (\`animation\`). Only \`opacity\` and
|
|
932
983
|
\`transform\` (\`translate\`, \`scale\`, \`rotate\`) animate off the main thread: they stay smooth while the page
|
|
933
984
|
hydrates and on a slow phone. Anything else repaints or lays the page out again on every frame, and freezes while the
|
|
@@ -940,7 +991,8 @@ page's scripts run.
|
|
|
940
991
|
pulsing glow is a static gradient whose \`opacity\` or \`scale\` changes.
|
|
941
992
|
- Decoration that must animate something else (a custom property, \`background-position\`) starts paused and runs
|
|
942
993
|
once the page is hydrated: \`.glow { animation: glow 8s linear infinite paused; } [data-hydrated] .glow {
|
|
943
|
-
animation-play-state: running; }\` in \`customCss\`.
|
|
994
|
+
animation-play-state: running; }\` in \`customCss\`. That is for loops: an entrance of its own that plays once
|
|
995
|
+
(\`transform\`/\`opacity\` only) plays from the first paint with \`backwards\`, never gated on \`[data-hydrated]\`.
|
|
944
996
|
- Entrances: \`opacity\` + a small \`translateY\`, under ~600ms, staggered by tens of ms.
|
|
945
997
|
- One slow ambient loop per screen at most — not one per card: \`infinite\` runs on every visitor's battery.
|
|
946
998
|
- Name what transitions (\`transition: transform 200ms, opacity 200ms\`), never \`all\`; \`will-change\` only on the
|
|
@@ -962,7 +1014,9 @@ tree names nothing is invisible to both, however it looks. So build every page t
|
|
|
962
1014
|
no agent finds them. An empty backdrop that closes a panel is the exception (the panel's close button and Escape
|
|
963
1015
|
are the ways everyone has).
|
|
964
1016
|
- **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.
|
|
1017
|
+
(bind them like any attribute) — an "active" class alone is invisible to both readers. A button that shows and
|
|
1018
|
+
hides a panel names it in \`controls\` (\`aria-controls\`, the panel's anchor), and words that change while a
|
|
1019
|
+
visitor reads them — a count, a total, a status — sit in a \`container\` with \`live: "polite"\` (\`aria-live\`).
|
|
966
1020
|
- **A dropdown opens from a \`button\`** among its children, outside the popup (an avatar, a "⋯": the button holds it and
|
|
967
1021
|
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
1022
|
keyboard.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { AIElementDetail } from '../types';
|
|
2
|
-
import { ActionEntry, ActionTaskDescriptor, ComponentCatalog, ConnectorEntry, Element, FunctionsDraft, PageFolder, Schema, Style } from '@plitzi/sdk-shared';
|
|
2
|
+
import { ActionEntry, ActionTaskDescriptor, ComponentCatalog, ConnectorEntry, DataDraft, Element, FunctionsDraft, PageFolder, Schema, Style } from '@plitzi/sdk-shared';
|
|
3
3
|
/** The working view the tools read and mutate: the two Plitzi schemas (elements + style), which the platform
|
|
4
4
|
* stores and persists as separate documents (Space model / Style model), plus the space's `connectors` — a third
|
|
5
5
|
* store (one row per connector) that a provider element points into by identifier. `catalog` is read-only
|
|
@@ -16,6 +16,9 @@ export interface Space {
|
|
|
16
16
|
/** The space's own functions — their source files, which copy of them this is, and what they declare. Absent when
|
|
17
17
|
* the deployment offers no functions: then there is nothing to read and every function op is refused. */
|
|
18
18
|
functions?: FunctionsDraft;
|
|
19
|
+
/** The space's own data — JSON its server providers read (`/data/<file>`), never served — and which copy of it this
|
|
20
|
+
* is. Absent when the deployment offers no data: then there is nothing to read and every data op is refused. */
|
|
21
|
+
data?: DataDraft;
|
|
19
22
|
catalog?: ComponentCatalog;
|
|
20
23
|
/**
|
|
21
24
|
* The whole document, when `schema` is a view of one tree of it — a component's, which an op addressed to a
|
|
@@ -6,6 +6,7 @@ var cloneSpace = (space) => ({
|
|
|
6
6
|
connectors: structuredClone(space.connectors),
|
|
7
7
|
actions: structuredClone(space.actions),
|
|
8
8
|
...space.functions ? { functions: structuredClone(space.functions) } : {},
|
|
9
|
+
...space.data ? { data: structuredClone(space.data) } : {},
|
|
9
10
|
...space.actionTasks ? { actionTasks: space.actionTasks } : {},
|
|
10
11
|
...space.catalog ? { catalog: space.catalog } : {}
|
|
11
12
|
});
|
|
@@ -28,6 +28,8 @@ export declare const actionUri: (env: Env, ref: string) => string;
|
|
|
28
28
|
export declare const actionTasksUri: (env: Env) => string;
|
|
29
29
|
export declare const functionsUri: (env: Env) => string;
|
|
30
30
|
export declare const functionFileUri: (env: Env, path: string) => string;
|
|
31
|
+
export declare const dataUri: (env: Env) => string;
|
|
32
|
+
export declare const dataFileUri: (env: Env, path: string) => string;
|
|
31
33
|
export declare const foldersUri: (env: Env) => string;
|
|
32
34
|
export declare const folderUri: (env: Env, ref: string) => string;
|
|
33
35
|
export declare const defsUri: (env: Env) => string;
|
|
@@ -28,6 +28,8 @@ var actionUri = (env, ref) => `plitzi://actions/${env}/${ref}`;
|
|
|
28
28
|
var actionTasksUri = (env) => `plitzi://actions/${env}/tasks`;
|
|
29
29
|
var functionsUri = (env) => `plitzi://functions/${env}`;
|
|
30
30
|
var functionFileUri = (env, path) => `plitzi://functions/${env}/${path}`;
|
|
31
|
+
var dataUri = (env) => `plitzi://data/${env}`;
|
|
32
|
+
var dataFileUri = (env, path) => `plitzi://data/${env}/${path}`;
|
|
31
33
|
var foldersUri = (env) => `plitzi://folders/${env}`;
|
|
32
34
|
var folderUri = (env, ref) => `plitzi://folders/${env}/${ref}`;
|
|
33
35
|
var defsUri = (env) => `plitzi://definitions/${env}`;
|
|
@@ -62,4 +64,4 @@ var itemTemplates = (env) => [
|
|
|
62
64
|
* family and extracts its ref in one step, without repeating the prefix string for both the startsWith and slice. */
|
|
63
65
|
var afterPrefix = (uri, prefix) => uri.startsWith(prefix) ? uri.slice(prefix.length) : void 0;
|
|
64
66
|
//#endregion
|
|
65
|
-
export { actionTasksUri, actionUri, actionsUri, afterPrefix, aliasedRoots, changesUri, componentsUri, connectorPresetsUri, connectorUri, connectorsUri, cssPropertiesUri, dataSourcesUri, defUri, defsUri, elementUri, flagsUri, folderUri, foldersUri, fontUri, fontsUri, functionFileUri, functionsUri, globalUri, globalsUri, guideUri, idUri, idsUri, interactionsUri, itemTemplates, layoutsUri, pageUri, pagesUri, primerUri, schemaVarsUri, settingsUri, styleVarUri, styleVarsUri, typesUri };
|
|
67
|
+
export { actionTasksUri, actionUri, actionsUri, afterPrefix, aliasedRoots, changesUri, componentsUri, connectorPresetsUri, connectorUri, connectorsUri, cssPropertiesUri, dataFileUri, dataSourcesUri, dataUri, defUri, defsUri, elementUri, flagsUri, folderUri, foldersUri, fontUri, fontsUri, functionFileUri, functionsUri, globalUri, globalsUri, guideUri, idUri, idsUri, interactionsUri, itemTemplates, layoutsUri, pageUri, pagesUri, primerUri, schemaVarsUri, settingsUri, styleVarUri, styleVarsUri, typesUri };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { createMcpServer, handleMcp, serveMcp, readMcpBody } from './handler';
|
|
2
2
|
export { readResource, resourceVersion, registerResources, buildTypeRegistry, cssProperties } from './resources';
|
|
3
3
|
export { apply, validate, search, read, validateOperations, operation, tools } from './tools';
|
|
4
|
-
export { computeVersion
|
|
4
|
+
export { computeVersion } from './helpers';
|
|
5
5
|
export { createHttpPreviewClient } from './previewClient';
|
|
6
6
|
export { createLocalScreenshotClient, resolveLocalBrowser } from './localScreenshotClient';
|
|
7
7
|
export { createHttpScreenshotClient } from './screenshotClient';
|