@plitzi/sdk-mcp 0.37.2 → 0.37.3

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.
Files changed (94) hide show
  1. package/CHANGELOG.md +1156 -0
  2. package/README.md +6 -2
  3. package/dist/createServer.js +1 -1
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js +2 -1
  6. package/dist/modules/mcp/accessibilityOutline.d.ts +38 -0
  7. package/dist/modules/mcp/accessibilityOutline.js +75 -0
  8. package/dist/modules/mcp/accessibilityOutline.test.d.ts +1 -0
  9. package/dist/modules/mcp/catalogs/index.d.ts +2 -2
  10. package/dist/modules/mcp/catalogs/index.js +2 -2
  11. package/dist/modules/mcp/catalogs/observed.js +2 -2
  12. package/dist/modules/mcp/catalogs/pluginCatalog.d.ts +6 -3
  13. package/dist/modules/mcp/catalogs/pluginCatalog.js +12 -7
  14. package/dist/modules/mcp/helpers/agentPrompt.js +22 -5
  15. package/dist/modules/mcp/helpers/guide.d.ts +2 -2
  16. package/dist/modules/mcp/helpers/guide.js +212 -48
  17. package/dist/modules/mcp/helpers/interactions.d.ts +2 -1
  18. package/dist/modules/mcp/helpers/interactions.js +2 -0
  19. package/dist/modules/mcp/helpers/space.d.ts +6 -4
  20. package/dist/modules/mcp/helpers/space.js +7 -20
  21. package/dist/modules/mcp/helpers/uris.d.ts +3 -1
  22. package/dist/modules/mcp/helpers/uris.js +4 -1
  23. package/dist/modules/mcp/index.d.ts +2 -0
  24. package/dist/modules/mcp/localScreenshotClient.d.ts +11 -0
  25. package/dist/modules/mcp/localScreenshotClient.js +24 -9
  26. package/dist/modules/mcp/proxy/guard.d.ts +6 -0
  27. package/dist/modules/mcp/proxy/guard.js +8 -12
  28. package/dist/modules/mcp/resources/functions.d.ts +8 -0
  29. package/dist/modules/mcp/resources/functions.js +35 -0
  30. package/dist/modules/mcp/resources/register.d.ts +2 -1
  31. package/dist/modules/mcp/resources/register.js +49 -2
  32. package/dist/modules/mcp/resources/renderGuide.js +3 -2
  33. package/dist/modules/mcp/resources/router.js +3 -1
  34. package/dist/modules/mcp/screenshotClient.js +12 -4
  35. package/dist/modules/mcp/server.js +20 -10
  36. package/dist/modules/mcp/tests/guide.test.d.ts +1 -0
  37. package/dist/modules/mcp/tools/apply/dispatch.js +9 -1
  38. package/dist/modules/mcp/tools/apply/index.d.ts +34 -0
  39. package/dist/modules/mcp/tools/apply/index.js +35 -70
  40. package/dist/modules/mcp/tools/index.js +4 -2
  41. package/dist/modules/mcp/tools/operations/connectors/manifest.d.ts +0 -1
  42. package/dist/modules/mcp/tools/operations/functions/functions.test.d.ts +1 -0
  43. package/dist/modules/mcp/tools/operations/functions/index.d.ts +31 -0
  44. package/dist/modules/mcp/tools/operations/functions/index.js +48 -0
  45. package/dist/modules/mcp/tools/operations/index.d.ts +122 -2
  46. package/dist/modules/mcp/tools/operations/index.js +4 -3
  47. package/dist/modules/mcp/tools/operations/schema/elements/deleteElement.js +5 -6
  48. package/dist/modules/mcp/tools/operations/schema/elements/moveElement.js +3 -11
  49. package/dist/modules/mcp/tools/operations/schema/elements/upsertElement.js +6 -9
  50. package/dist/modules/mcp/tools/operations/schema/interactions/patchInteractionNode.d.ts +5 -0
  51. package/dist/modules/mcp/tools/operations/schema/interactions/patchInteractionNode.js +3 -1
  52. package/dist/modules/mcp/tools/operations/schema/interactions/upsertInteractionFlow.d.ts +5 -0
  53. package/dist/modules/mcp/tools/operations/schema/operations.d.ts +27 -0
  54. package/dist/modules/mcp/tools/operations/schema/pages/deleteLayout.js +6 -5
  55. package/dist/modules/mcp/tools/operations/schema/pages/deletePage.js +6 -5
  56. package/dist/modules/mcp/tools/operations/schema/settings/patchSettings.d.ts +17 -0
  57. package/dist/modules/mcp/tools/operations/schema/settings/patchSettings.js +34 -5
  58. package/dist/modules/mcp/tools/operations/schema/shared.d.ts +6 -0
  59. package/dist/modules/mcp/tools/operations/schema/shared.js +5 -0
  60. package/dist/modules/mcp/tools/operations/schema/translator.js +3 -2
  61. package/dist/modules/mcp/tools/operations/schema/write.d.ts +10 -5
  62. package/dist/modules/mcp/tools/operations/schema/write.js +16 -16
  63. package/dist/modules/mcp/tools/preview.d.ts +27 -0
  64. package/dist/modules/mcp/tools/render.d.ts +27 -0
  65. package/dist/modules/mcp/tools/render.js +7 -43
  66. package/dist/modules/mcp/tools/screenshot.d.ts +39 -0
  67. package/dist/modules/mcp/tools/screenshot.js +40 -5
  68. package/dist/modules/mcp/tools/shared/draftBatch.d.ts +25 -0
  69. package/dist/modules/mcp/tools/shared/draftBatch.js +58 -0
  70. package/dist/modules/mcp/tools/shared/draftBatch.test.d.ts +1 -0
  71. package/dist/modules/mcp/tools/shared/lintDraft.d.ts +30 -0
  72. package/dist/modules/mcp/tools/shared/lintDraft.js +142 -0
  73. package/dist/modules/mcp/tools/shared/lintDraft.test.d.ts +1 -0
  74. package/dist/modules/mcp/tools/shared/tool.d.ts +4 -0
  75. package/dist/modules/mcp/tools/shared/validator/bindings.d.ts +0 -4
  76. package/dist/modules/mcp/tools/shared/validator/bindings.js +1 -60
  77. package/dist/modules/mcp/tools/shared/validator/elements.js +3 -15
  78. package/dist/modules/mcp/tools/shared/validator/index.d.ts +1 -4
  79. package/dist/modules/mcp/tools/shared/validator/index.js +25 -20
  80. package/dist/modules/mcp/tools/shared/validator/interactions.js +3 -58
  81. package/dist/modules/mcp/tools/tryFunction.d.ts +18 -0
  82. package/dist/modules/mcp/tools/tryFunction.js +43 -0
  83. package/dist/modules/mcp/tools/validate.d.ts +34 -0
  84. package/dist/modules/mcp/tools/validate.js +9 -26
  85. package/dist/modules/mcp/types/aiSchema.d.ts +8 -1
  86. package/dist/modules/mcp/types/previewTypes.d.ts +6 -0
  87. package/dist/modules/mcp/types/screenshotTypes.d.ts +16 -0
  88. package/dist/modules/mcp/types/toolTypes.d.ts +5 -1
  89. package/dist/preview/createPreview.js +5 -4
  90. package/dist/stages/preview.js +15 -1
  91. package/package.json +11 -10
  92. package/skills/plitzi-render/SKILL.md +1 -2
  93. package/dist/modules/mcp/tools/shared/validator/audit.d.ts +0 -4
  94. package/dist/modules/mcp/tools/shared/validator/audit.js +0 -127
@@ -19,6 +19,11 @@ export declare const upsertInteractionFlowOp: z.ZodObject<{
19
19
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
20
20
  enabled: z.ZodOptional<z.ZodBoolean>;
21
21
  when: z.ZodOptional<z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>>;
22
+ whileRunning: z.ZodOptional<z.ZodEnum<{
23
+ skip: "skip";
24
+ parallel: "parallel";
25
+ queue: "queue";
26
+ }>>;
22
27
  elementId: z.ZodOptional<z.ZodString>;
23
28
  preview: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
24
29
  }, z.core.$strip>>;
@@ -201,6 +201,11 @@ export declare const elementOps: {
201
201
  params: import('zod').ZodOptional<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>;
202
202
  enabled: import('zod').ZodOptional<import('zod').ZodBoolean>;
203
203
  when: import('zod').ZodOptional<import('zod').ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, import('zod/v4/core').$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>>;
204
+ whileRunning: import('zod').ZodOptional<import('zod').ZodEnum<{
205
+ skip: "skip";
206
+ parallel: "parallel";
207
+ queue: "queue";
208
+ }>>;
204
209
  elementId: import('zod').ZodOptional<import('zod').ZodString>;
205
210
  preview: import('zod').ZodOptional<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>;
206
211
  }, import('zod/v4/core').$strip>>;
@@ -215,6 +220,11 @@ export declare const elementOps: {
215
220
  params: import('zod').ZodOptional<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>;
216
221
  enabled: import('zod').ZodOptional<import('zod').ZodBoolean>;
217
222
  when: import('zod').ZodOptional<import('zod').ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, import('zod/v4/core').$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>>;
223
+ whileRunning: import('zod').ZodOptional<import('zod').ZodEnum<{
224
+ skip: "skip";
225
+ parallel: "parallel";
226
+ queue: "queue";
227
+ }>>;
218
228
  elementId: import('zod').ZodOptional<import('zod').ZodString>;
219
229
  preview: import('zod').ZodOptional<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodUnknown>>;
220
230
  }, import('zod/v4/core').$strip>;
@@ -233,6 +243,8 @@ export declare const elementOps: {
233
243
  localStorage: "localStorage";
234
244
  sessionStorage: "sessionStorage";
235
245
  }>>;
246
+ transientState: import('zod').ZodOptional<import('zod').ZodArray<import('zod').ZodString>>;
247
+ paintedState: import('zod').ZodOptional<import('zod').ZodArray<import('zod').ZodString>>;
236
248
  userProvider: import('zod').ZodOptional<import('zod').ZodString>;
237
249
  tokenStorage: import('zod').ZodOptional<import('zod').ZodEnum<{
238
250
  "": "";
@@ -255,5 +267,20 @@ export declare const elementOps: {
255
267
  strict: "strict";
256
268
  }>>;
257
269
  sessionRevalidateSeconds: import('zod').ZodOptional<import('zod').ZodNumber>;
270
+ channels: import('zod').ZodOptional<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodNullable<import('zod').ZodObject<{
271
+ access: import('zod').ZodObject<{
272
+ mode: import('zod').ZodEnum<{
273
+ public: "public";
274
+ session: "session";
275
+ role: "role";
276
+ }>;
277
+ permissions: import('zod').ZodOptional<import('zod').ZodArray<import('zod').ZodString>>;
278
+ }, import('zod/v4/core').$strip>;
279
+ publish: import('zod').ZodOptional<import('zod').ZodEnum<{
280
+ server: "server";
281
+ clients: "clients";
282
+ }>>;
283
+ presence: import('zod').ZodOptional<import('zod').ZodBoolean>;
284
+ }, import('zod/v4/core').$strip>>>>;
258
285
  }, import('zod/v4/core').$strip>;
259
286
  };
@@ -1,6 +1,7 @@
1
- import { descendantIds, findLayoutByRef, indexRemoveLayout, pagesUsingLayout } from "../../../../helpers/space.js";
1
+ import { findLayoutByRef, indexRemoveLayout, pagesUsingLayout } from "../../../../helpers/space.js";
2
2
  import { layoutsUri, pageUri } from "../../../../helpers/uris.js";
3
3
  import { empty, fail } from "../../../../helpers/opResult.js";
4
+ import { descendants } from "@plitzi/sdk-schema/helpers/elementTree";
4
5
  import { z } from "zod";
5
6
  //#region src/modules/mcp/tools/operations/schema/pages/deleteLayout.ts
6
7
  var deleteLayoutOp = z.object({
@@ -19,10 +20,10 @@ var deleteLayout = (space, env, op) => {
19
20
  */
20
21
  const inUse = pagesUsingLayout(space.schema, layout.id);
21
22
  if (inUse.length > 0) return fail("ref", `Layout "${op.ref}" is still used by ${inUse.length} page(s): ${inUse.map((page) => page.id).join(", ")}`, "Detach them first with upsertPage { layout: null }, or point them at another shell");
22
- const descendantElementIds = descendantIds(space.schema, layout.id);
23
- const descendants = descendantElementIds.map((id) => space.schema.flat[id]);
24
- for (const id of [...descendantElementIds, layout.id]) Reflect.deleteProperty(space.schema.flat, id);
25
- indexRemoveLayout(space.schema, layout, descendants);
23
+ const removedIds = descendants(space.schema.flat, layout.id);
24
+ const removed = removedIds.map((id) => space.schema.flat[id]);
25
+ for (const id of [...removedIds, layout.id]) Reflect.deleteProperty(space.schema.flat, id);
26
+ indexRemoveLayout(space.schema, layout, removed);
26
27
  return {
27
28
  ...empty(),
28
29
  deleted: 1,
@@ -1,6 +1,7 @@
1
- import { descendantIds, findPageByRef, indexRemovePage } from "../../../../helpers/space.js";
1
+ import { findPageByRef, indexRemovePage } from "../../../../helpers/space.js";
2
2
  import { pageUri, pagesUri } from "../../../../helpers/uris.js";
3
3
  import { empty, fail } from "../../../../helpers/opResult.js";
4
+ import { descendants } from "@plitzi/sdk-schema/helpers/elementTree";
4
5
  import { z } from "zod";
5
6
  //#region src/modules/mcp/tools/operations/schema/pages/deletePage.ts
6
7
  var deletePageOp = z.object({
@@ -10,11 +11,11 @@ var deletePageOp = z.object({
10
11
  var deletePage = (space, env, op) => {
11
12
  const page = findPageByRef(space.schema, op.ref);
12
13
  if (!page) return fail("ref", `Page "${op.ref}" not found`, "Read the pages resource for valid refs");
13
- const descendantElementIds = descendantIds(space.schema, page.id);
14
- const descendants = descendantElementIds.map((id) => space.schema.flat[id]);
15
- for (const id of [...descendantElementIds, page.id]) Reflect.deleteProperty(space.schema.flat, id);
14
+ const removedIds = descendants(space.schema.flat, page.id);
15
+ const removed = removedIds.map((id) => space.schema.flat[id]);
16
+ for (const id of [...removedIds, page.id]) Reflect.deleteProperty(space.schema.flat, id);
16
17
  space.schema.pages = space.schema.pages.filter((id) => id !== page.id);
17
- indexRemovePage(space.schema, page, descendants);
18
+ indexRemovePage(space.schema, page, removed);
18
19
  return {
19
20
  ...empty(),
20
21
  deleted: 1,
@@ -9,6 +9,8 @@ export declare const patchSettingsOp: z.ZodObject<{
9
9
  localStorage: "localStorage";
10
10
  sessionStorage: "sessionStorage";
11
11
  }>>;
12
+ transientState: z.ZodOptional<z.ZodArray<z.ZodString>>;
13
+ paintedState: z.ZodOptional<z.ZodArray<z.ZodString>>;
12
14
  userProvider: z.ZodOptional<z.ZodString>;
13
15
  tokenStorage: z.ZodOptional<z.ZodEnum<{
14
16
  "": "";
@@ -31,6 +33,21 @@ export declare const patchSettingsOp: z.ZodObject<{
31
33
  strict: "strict";
32
34
  }>>;
33
35
  sessionRevalidateSeconds: z.ZodOptional<z.ZodNumber>;
36
+ channels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodObject<{
37
+ access: z.ZodObject<{
38
+ mode: z.ZodEnum<{
39
+ public: "public";
40
+ session: "session";
41
+ role: "role";
42
+ }>;
43
+ permissions: z.ZodOptional<z.ZodArray<z.ZodString>>;
44
+ }, z.core.$strip>;
45
+ publish: z.ZodOptional<z.ZodEnum<{
46
+ server: "server";
47
+ clients: "clients";
48
+ }>>;
49
+ presence: z.ZodOptional<z.ZodBoolean>;
50
+ }, z.core.$strip>>>>;
34
51
  }, z.core.$strip>;
35
52
  export type PatchSettings = z.infer<typeof patchSettingsOp>;
36
53
  export declare const patchSettings: (space: Space, env: Env, op: PatchSettings) => OpResult;
@@ -1,6 +1,7 @@
1
1
  import { settingsUri } from "../../../../helpers/uris.js";
2
- import { empty } from "../../../../helpers/opResult.js";
2
+ import { empty, fail } from "../../../../helpers/opResult.js";
3
3
  import { z } from "zod";
4
+ import { channelProblems } from "@plitzi/sdk-shared/realtime";
4
5
  //#region src/modules/mcp/tools/operations/schema/settings/patchSettings.ts
5
6
  var userProvider = z.string();
6
7
  var storage = z.enum([
@@ -8,11 +9,25 @@ var storage = z.enum([
8
9
  "sessionStorage",
9
10
  ""
10
11
  ]);
12
+ var channel = z.object({
13
+ access: z.object({
14
+ mode: z.enum([
15
+ "public",
16
+ "session",
17
+ "role"
18
+ ]),
19
+ permissions: z.array(z.string()).optional()
20
+ }),
21
+ publish: z.enum(["clients", "server"]).optional(),
22
+ presence: z.boolean().optional()
23
+ });
11
24
  var patchSettingsOp = z.object({
12
25
  type: z.literal("patchSettings"),
13
26
  customCss: z.string().optional().describe("Raw global CSS for the whole space (keyframes, @font-face, resets)"),
14
- keepState: z.boolean().optional().describe("Persist element state across reloads"),
27
+ keepState: z.boolean().optional().describe("Keep runtime state (setState keys) across reloads"),
15
28
  stateStorage: z.enum(["localStorage", "sessionStorage"]).optional(),
29
+ transientState: z.array(z.string()).optional().describe("Top-level state keys never kept"),
30
+ paintedState: z.array(z.string()).optional().describe("Kept keys the first paint shows"),
16
31
  userProvider: userProvider.optional().describe("Auth provider: \"basic\" for an HTTP+JSON backend, a registered name, or \"\" to disable auth"),
17
32
  tokenStorage: storage.optional(),
18
33
  loginUrl: z.string().optional(),
@@ -27,12 +42,26 @@ var patchSettingsOp = z.object({
27
42
  sessionHintCookie: z.string().optional().describe("Readable cookie holding only session expiries, so a page can tell nobody is signed in with no request"),
28
43
  sessionExchangeUrl: z.string().optional().describe("Where to hand a browser-obtained credential so the server issues its own session (client-side IdPs)"),
29
44
  sessionGate: z.enum(["optimistic", "strict"]).optional().describe("Render from the stored session and confirm behind it (default), or wait for the confirmation"),
30
- sessionRevalidateSeconds: z.number().optional()
31
- }).describe("Merge space-level settings: the global CSS (customCss) and the state/auth (user-provider) configuration. Only the fields you pass change; the rest are preserved. Use customCss for site-wide CSS, never to style one element (attach a definition for that).");
45
+ sessionRevalidateSeconds: z.number().optional(),
46
+ channels: z.record(z.string(), channel.nullable()).optional().describe("Realtime channels by topic pattern (`board:{id}`); null removes one. See the guide")
47
+ }).describe("Merge space-level settings — global CSS, kept state, auth, realtime channels. Only the fields sent change. customCss is for site-wide CSS, never to style one element (attach a definition for that).");
48
+ /** The space's channels with the patch merged in, pattern by pattern — `null` takes one out. */
49
+ var mergeChannels = (current, patch) => {
50
+ const merged = {
51
+ ...current,
52
+ ...patch
53
+ };
54
+ return Object.fromEntries(Object.entries(merged).filter((entry) => entry[1] !== null));
55
+ };
32
56
  var patchSettings = (space, env, op) => {
33
- const { type, ...patch } = op;
57
+ const { type, channels, ...patch } = op;
58
+ for (const [pattern, declaration] of Object.entries(channels ?? {})) {
59
+ const [problem] = declaration === null ? [] : channelProblems(pattern, declaration);
60
+ if (problem) return fail(`channels["${pattern}"]`, `Channel "${pattern}": ${problem}.`, "Fix the pattern or declaration and send it again");
61
+ }
34
62
  const next = { ...space.schema.settings };
35
63
  for (const [key, value] of Object.entries(patch)) next[key] = value;
64
+ if (channels) next.channels = mergeChannels(space.schema.settings.channels, channels);
36
65
  space.schema.settings = next;
37
66
  return {
38
67
  ...empty(),
@@ -63,6 +63,7 @@ export declare const position: z.ZodEnum<{
63
63
  before: "before";
64
64
  after: "after";
65
65
  }>;
66
+ export type Position = z.infer<typeof position>;
66
67
  export declare const scalar: z.ZodUnion<readonly [z.ZodString, z.ZodNumber, z.ZodBoolean]>;
67
68
  export declare const bindingCategory: z.ZodEnum<{
68
69
  attributes: "attributes";
@@ -100,6 +101,11 @@ export declare const interactionNode: z.ZodObject<{
100
101
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
101
102
  enabled: z.ZodOptional<z.ZodBoolean>;
102
103
  when: z.ZodOptional<z.ZodType<RuleGroup, unknown, z.core.$ZodTypeInternals<RuleGroup, unknown>>>;
104
+ whileRunning: z.ZodOptional<z.ZodEnum<{
105
+ skip: "skip";
106
+ parallel: "parallel";
107
+ queue: "queue";
108
+ }>>;
103
109
  elementId: z.ZodOptional<z.ZodString>;
104
110
  preview: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
105
111
  }, z.core.$strip>;
@@ -124,6 +124,11 @@ var interactionNode = z.object({
124
124
  params: z.record(z.string(), z.unknown()).optional(),
125
125
  enabled: z.boolean().optional(),
126
126
  when: ruleGroup.optional().describe("QueryBuilder RuleGroup gating this step (validated structurally)"),
127
+ whileRunning: z.enum([
128
+ "skip",
129
+ "parallel",
130
+ "queue"
131
+ ]).optional().describe("Trigger only: a refiring while this flow runs"),
127
132
  elementId: z.string().optional().describe("Element whose callback this step invokes, by name; defaults to this element"),
128
133
  preview: z.record(z.string(), z.unknown()).optional()
129
134
  });
@@ -1,7 +1,8 @@
1
1
  import { computeVersion } from "../../../helpers/computeVersion.js";
2
- import { descendantCount, descendantIds, elementById, getLayoutElements, getPageElements, nameOf, orderedChildren, pageFoldersOf, pageRefOfElement, pagesUsingLayout, slugRouteParams, spaceIndex, strOr } from "../../../helpers/space.js";
2
+ import { descendantCount, elementById, getLayoutElements, getPageElements, nameOf, orderedChildren, pageFoldersOf, pageRefOfElement, pagesUsingLayout, slugRouteParams, spaceIndex, strOr } from "../../../helpers/space.js";
3
3
  import { bindingsToAI, flowsFromInteractions } from "../../../helpers/interactions.js";
4
4
  import { definitionToAI, globalStylesForType, idStyleToAI } from "../style/translator.js";
5
+ import { descendants } from "@plitzi/sdk-schema/helpers/elementTree";
5
6
  //#region src/modules/mcp/tools/operations/schema/translator.ts
6
7
  var splitClasses = (value) => value ? value.split(/\s+/).filter(Boolean) : [];
7
8
  var propsOf = (el) => {
@@ -99,7 +100,7 @@ var pageStylesToAI = (schema, style, pageEl) => {
99
100
  types.add(el.definition.type);
100
101
  };
101
102
  collect(pageEl);
102
- for (const id of descendantIds(schema, pageEl.id)) {
103
+ for (const id of descendants(schema.flat, pageEl.id)) {
103
104
  const el = elementById(schema, id);
104
105
  if (el) collect(el);
105
106
  }
@@ -1,7 +1,7 @@
1
- import { ElementInput, InitialStateInput } from './shared';
1
+ import { ElementInput, InitialStateInput, Position } from './shared';
2
2
  import { OpResult, Space } from '../../../helpers';
3
3
  import { Env } from '../../../types';
4
- import { Element } from '@plitzi/sdk-shared';
4
+ import { DropPosition, Element } from '@plitzi/sdk-shared';
5
5
  export declare const ID_REF_HINT: string;
6
6
  /** Every name in an element input tree (the element plus its nested children) — each becomes an element's id. */
7
7
  export declare const collectInputRefs: (input: ElementInput) => string[];
@@ -10,10 +10,15 @@ export declare const collectInputRefs: (input: ElementInput) => string[];
10
10
  * the builder and the schema validator enforce. Null when the name is usable. */
11
11
  export declare const guardNewRef: (space: Space, ref: string, field: string) => OpResult | null;
12
12
  export { folderUri, foldersUri, layoutsUri, pageUri, pagesUri, schemaVarsUri, settingsUri } from '../../../helpers';
13
- export declare const removeFromParent: (space: Space, child: Element) => void;
14
- export declare const placeChild: (parent: Element, childId: string, index?: number) => void;
13
+ /** Where an op's `position` puts an element, in the vocabulary of the tree operations every writer shares. */
14
+ export declare const DROP_POSITION: Record<Position, DropPosition>;
15
15
  export declare const writeInitialState: (el: Element, input: InitialStateInput, merge: boolean) => void;
16
- export declare const createElement: (space: Space, page: Element, input: ElementInput, parent: Element, index: number | undefined) => void;
16
+ /**
17
+ * Creates an element from its input, and its children inside it, through `FlatMap` — the same insertion the builder,
18
+ * the server and `authorSpace` make, so a tree the MCP writes is held to exactly their rules. False when the anchor
19
+ * cannot take it: before/after an element with no parent, or inside one that holds no items.
20
+ */
21
+ export declare const createElement: (space: Space, page: Element, input: ElementInput, anchorId: string, drop: DropPosition) => boolean;
17
22
  /** The key an interaction node must store to reach a target element — which is simply that element's name, since
18
23
  * the name it is addressed by and the key the runtime registers callbacks under are now the same thing. A target
19
24
  * that resolves to no element is left as written: it is a source module (`space`, `state`) or a key only a plugin
@@ -2,6 +2,7 @@ import { findRootByRef, indexAddElement, resolveRef } from "../../../helpers/spa
2
2
  import { folderUri, foldersUri, layoutsUri, pageUri, pagesUri, schemaVarsUri, settingsUri } from "../../../helpers/uris.js";
3
3
  import { fail } from "../../../helpers/opResult.js";
4
4
  import { elementIdConflict, isValidElementId } from "@plitzi/sdk-schema/helpers/elementId";
5
+ import FlatMap from "@plitzi/sdk-schema/helpers/FlatMap";
5
6
  //#region src/modules/mcp/tools/operations/schema/write.ts
6
7
  var ID_REF_HINT = "Start with a letter, then letters, numbers, hyphens and underscores (e.g. \"hero-cta\" or \"food_item\"). The name IS the element id, which the runtime embeds in source names like `apiContainer_<id>.field` and in interaction targets — a dot would split those paths (an underscore is fine: the FIRST `_` separates the type from the id, and element types carry none, so extra underscores are unambiguous).";
7
8
  var TAKEN_HINT = "A name must be unique across the space — pick a different one, or address the existing element by this name.";
@@ -15,14 +16,11 @@ var guardNewRef = (space, ref, field) => {
15
16
  if (!conflict) return null;
16
17
  return isValidElementId(ref) ? fail(field, conflict, TAKEN_HINT) : fail(field, conflict, ID_REF_HINT);
17
18
  };
18
- var removeFromParent = (space, child) => {
19
- const parent = child.definition.parentId ? space.schema.flat[child.definition.parentId] : void 0;
20
- if (parent?.definition.items) parent.definition.items = parent.definition.items.filter((id) => id !== child.id);
21
- };
22
- var placeChild = (parent, childId, index) => {
23
- const items = parent.definition.items ?? (parent.definition.items = []);
24
- if (index === void 0 || index < 0 || index >= items.length) items.push(childId);
25
- else items.splice(index, 0, childId);
19
+ /** Where an op's `position` puts an element, in the vocabulary of the tree operations every writer shares. */
20
+ var DROP_POSITION = {
21
+ inside: "inside",
22
+ before: "top",
23
+ after: "bottom"
26
24
  };
27
25
  var writeInitialState = (el, input, merge) => {
28
26
  const current = el.definition.initialState ?? {};
@@ -40,23 +38,26 @@ var writeInitialState = (el, input, merge) => {
40
38
  if (input.visibility !== void 0) next.visibility = input.visibility;
41
39
  el.definition.initialState = next;
42
40
  };
43
- var createElement = (space, page, input, parent, index) => {
41
+ /**
42
+ * Creates an element from its input, and its children inside it, through `FlatMap` — the same insertion the builder,
43
+ * the server and `authorSpace` make, so a tree the MCP writes is held to exactly their rules. False when the anchor
44
+ * cannot take it: before/after an element with no parent, or inside one that holds no items.
45
+ */
46
+ var createElement = (space, page, input, anchorId, drop) => {
44
47
  const { subType, ...props } = {
45
48
  subType: input.subType,
46
49
  ...input.props
47
50
  };
48
51
  const styleSelectors = { base: (input.style?.base ?? []).join(" ") };
49
52
  for (const [slot, classes] of Object.entries(input.style?.slots ?? {})) styleSelectors[slot] = classes.join(" ");
50
- const id = input.ref;
51
53
  const el = {
52
- id,
54
+ id: input.ref,
53
55
  attributes: subType === void 0 ? props : {
54
56
  subType,
55
57
  ...props
56
58
  },
57
59
  definition: {
58
60
  rootId: page.id,
59
- parentId: parent.id,
60
61
  label: input.label ?? input.ref,
61
62
  type: input.type,
62
63
  items: [],
@@ -64,11 +65,10 @@ var createElement = (space, page, input, parent, index) => {
64
65
  ...input.runtime === void 0 ? {} : { runtime: input.runtime }
65
66
  }
66
67
  };
67
- space.schema.flat[id] = el;
68
- placeChild(parent, id, index);
68
+ if (!new FlatMap({ flat: space.schema.flat }).addElement(el, anchorId, drop)) return false;
69
69
  indexAddElement(space.schema, el, page.id);
70
70
  if (input.initialState) writeInitialState(el, input.initialState, false);
71
- for (const child of input.children ?? []) createElement(space, page, child, el, void 0);
71
+ return (input.children ?? []).every((child) => createElement(space, page, child, el.id, "inside"));
72
72
  };
73
73
  /** The key an interaction node must store to reach a target element — which is simply that element's name, since
74
74
  * the name it is addressed by and the key the runtime registers callbacks under are now the same thing. A target
@@ -89,4 +89,4 @@ var resolveElement = (space, env, pageRef, ref) => {
89
89
  return { el };
90
90
  };
91
91
  //#endregion
92
- export { ID_REF_HINT, collectInputRefs, createElement, folderUri, foldersUri, guardNewRef, layoutsUri, pageUri, pagesUri, placeChild, removeFromParent, resolveElement, resolveTargetRef, schemaVarsUri, settingsUri, writeInitialState };
92
+ export { DROP_POSITION, ID_REF_HINT, collectInputRefs, createElement, folderUri, foldersUri, guardNewRef, layoutsUri, pageUri, pagesUri, resolveElement, resolveTargetRef, schemaVarsUri, settingsUri, writeInitialState };
@@ -187,6 +187,11 @@ export declare const previewShape: {
187
187
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
188
188
  enabled: z.ZodOptional<z.ZodBoolean>;
189
189
  when: z.ZodOptional<z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>>;
190
+ whileRunning: z.ZodOptional<z.ZodEnum<{
191
+ skip: "skip";
192
+ parallel: "parallel";
193
+ queue: "queue";
194
+ }>>;
190
195
  elementId: z.ZodOptional<z.ZodString>;
191
196
  preview: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
192
197
  }, z.core.$strip>>;
@@ -200,6 +205,11 @@ export declare const previewShape: {
200
205
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
201
206
  enabled: z.ZodOptional<z.ZodBoolean>;
202
207
  when: z.ZodOptional<z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>>;
208
+ whileRunning: z.ZodOptional<z.ZodEnum<{
209
+ skip: "skip";
210
+ parallel: "parallel";
211
+ queue: "queue";
212
+ }>>;
203
213
  elementId: z.ZodOptional<z.ZodString>;
204
214
  preview: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
205
215
  }, z.core.$strip>, z.ZodObject<{
@@ -216,6 +226,8 @@ export declare const previewShape: {
216
226
  localStorage: "localStorage";
217
227
  sessionStorage: "sessionStorage";
218
228
  }>>;
229
+ transientState: z.ZodOptional<z.ZodArray<z.ZodString>>;
230
+ paintedState: z.ZodOptional<z.ZodArray<z.ZodString>>;
219
231
  userProvider: z.ZodOptional<z.ZodString>;
220
232
  tokenStorage: z.ZodOptional<z.ZodEnum<{
221
233
  "": "";
@@ -238,6 +250,21 @@ export declare const previewShape: {
238
250
  strict: "strict";
239
251
  }>>;
240
252
  sessionRevalidateSeconds: z.ZodOptional<z.ZodNumber>;
253
+ channels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodObject<{
254
+ access: z.ZodObject<{
255
+ mode: z.ZodEnum<{
256
+ public: "public";
257
+ session: "session";
258
+ role: "role";
259
+ }>;
260
+ permissions: z.ZodOptional<z.ZodArray<z.ZodString>>;
261
+ }, z.core.$strip>;
262
+ publish: z.ZodOptional<z.ZodEnum<{
263
+ server: "server";
264
+ clients: "clients";
265
+ }>>;
266
+ presence: z.ZodOptional<z.ZodBoolean>;
267
+ }, z.core.$strip>>>>;
241
268
  }, z.core.$strip>, z.ZodObject<{
242
269
  desktop: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
243
270
  tablet: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
@@ -189,6 +189,11 @@ export declare const renderShape: {
189
189
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
190
190
  enabled: z.ZodOptional<z.ZodBoolean>;
191
191
  when: z.ZodOptional<z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>>;
192
+ whileRunning: z.ZodOptional<z.ZodEnum<{
193
+ skip: "skip";
194
+ parallel: "parallel";
195
+ queue: "queue";
196
+ }>>;
192
197
  elementId: z.ZodOptional<z.ZodString>;
193
198
  preview: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
194
199
  }, z.core.$strip>>;
@@ -202,6 +207,11 @@ export declare const renderShape: {
202
207
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
203
208
  enabled: z.ZodOptional<z.ZodBoolean>;
204
209
  when: z.ZodOptional<z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>>;
210
+ whileRunning: z.ZodOptional<z.ZodEnum<{
211
+ skip: "skip";
212
+ parallel: "parallel";
213
+ queue: "queue";
214
+ }>>;
205
215
  elementId: z.ZodOptional<z.ZodString>;
206
216
  preview: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
207
217
  }, z.core.$strip>, z.ZodObject<{
@@ -218,6 +228,8 @@ export declare const renderShape: {
218
228
  localStorage: "localStorage";
219
229
  sessionStorage: "sessionStorage";
220
230
  }>>;
231
+ transientState: z.ZodOptional<z.ZodArray<z.ZodString>>;
232
+ paintedState: z.ZodOptional<z.ZodArray<z.ZodString>>;
221
233
  userProvider: z.ZodOptional<z.ZodString>;
222
234
  tokenStorage: z.ZodOptional<z.ZodEnum<{
223
235
  "": "";
@@ -240,6 +252,21 @@ export declare const renderShape: {
240
252
  strict: "strict";
241
253
  }>>;
242
254
  sessionRevalidateSeconds: z.ZodOptional<z.ZodNumber>;
255
+ channels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodObject<{
256
+ access: z.ZodObject<{
257
+ mode: z.ZodEnum<{
258
+ public: "public";
259
+ session: "session";
260
+ role: "role";
261
+ }>;
262
+ permissions: z.ZodOptional<z.ZodArray<z.ZodString>>;
263
+ }, z.core.$strip>;
264
+ publish: z.ZodOptional<z.ZodEnum<{
265
+ server: "server";
266
+ clients: "clients";
267
+ }>>;
268
+ presence: z.ZodOptional<z.ZodBoolean>;
269
+ }, z.core.$strip>>>>;
243
270
  }, z.core.$strip>, z.ZodObject<{
244
271
  desktop: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
245
272
  tablet: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
@@ -3,15 +3,11 @@ import { RENDER_APP_URI } from "../apps/render/index.js";
3
3
  import { emptySpace } from "../helpers/space.js";
4
4
  import { proxifyResources } from "../proxy/rewrite.js";
5
5
  import { documentOperations } from "./operations/index.js";
6
- import { applyOperations } from "./apply/dispatch.js";
7
- import { expandOperations } from "./shared/expandOperations.js";
6
+ import { draftBatch } from "./shared/draftBatch.js";
8
7
  import { defineTool } from "./shared/tool.js";
9
- import { validateOperations } from "./shared/validator/index.js";
10
- import { auditResources } from "./shared/validator/audit.js";
11
8
  import { interactionReport } from "./shared/interactionReport.js";
12
9
  import { randomUUID } from "node:crypto";
13
10
  import { z } from "zod";
14
- import { validateSchema } from "@plitzi/sdk-schema/helpers/schemaValidator";
15
11
  import { generateCache } from "@plitzi/sdk-style/StyleHelper";
16
12
  //#region src/modules/mcp/tools/render.ts
17
13
  var HOST_PAGE_REF = "render";
@@ -43,47 +39,15 @@ var renderShape = {
43
39
  renderId: z.string().optional().describe("Handle returned by a previous render. Required with patch:true; it names the widget being changed.")
44
40
  };
45
41
  var render = (input, options = {}) => {
46
- const space = seedSpace();
47
- const expansion = expandOperations(input.operations);
48
- if (expansion.errors.length > 0) return {
42
+ const result = draftBatch(seedSpace(), "main", input.operations, "widget");
43
+ if (!result.ok) return {
49
44
  rendered: false,
50
- errors: expansion.errors
45
+ errors: result.errors,
46
+ warnings: noWarnings(result.warnings)
51
47
  };
52
- const ops = expansion.operations;
53
- const validation = validateOperations(space, ops, "widget");
54
- if (!validation.valid) return {
55
- rendered: false,
56
- errors: validation.errors,
57
- warnings: noWarnings(validation.warnings)
58
- };
59
- const outcome = applyOperations(space, "main", ops);
60
- if (outcome.errors.length > 0) return {
61
- rendered: false,
62
- errors: outcome.errors,
63
- warnings: noWarnings(validation.warnings)
64
- };
65
- const integrity = validateSchema(space.schema);
66
- if (!integrity.valid) return {
67
- rendered: false,
68
- errors: integrity.errors.map((error) => ({
69
- path: error.elementId ? `schema.${error.elementId}` : "schema",
70
- message: error.message,
71
- hint: "The authored widget is structurally inconsistent (broken parent/child link or a cycle)."
72
- })),
73
- warnings: noWarnings(validation.warnings)
74
- };
75
- const audit = auditResources(space, ops);
48
+ const { ops, draft: space } = result;
76
49
  const behaviour = interactionReport(space);
77
- const warnings = [
78
- ...validation.warnings,
79
- ...audit.warnings,
80
- ...behaviour.warnings
81
- ];
82
- if (audit.errors.length > 0) return {
83
- rendered: false,
84
- errors: audit.errors,
85
- warnings: noWarnings(warnings)
86
- };
50
+ const warnings = [...result.warnings, ...behaviour.warnings];
87
51
  if (options.proxy) warnings.push(...proxifyResources(space, options.proxy));
88
52
  space.style.cache = generateCache(space.style);
89
53
  return {
@@ -187,6 +187,11 @@ export declare const screenshotShape: {
187
187
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
188
188
  enabled: z.ZodOptional<z.ZodBoolean>;
189
189
  when: z.ZodOptional<z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>>;
190
+ whileRunning: z.ZodOptional<z.ZodEnum<{
191
+ skip: "skip";
192
+ parallel: "parallel";
193
+ queue: "queue";
194
+ }>>;
190
195
  elementId: z.ZodOptional<z.ZodString>;
191
196
  preview: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
192
197
  }, z.core.$strip>>;
@@ -200,6 +205,11 @@ export declare const screenshotShape: {
200
205
  params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
201
206
  enabled: z.ZodOptional<z.ZodBoolean>;
202
207
  when: z.ZodOptional<z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>>;
208
+ whileRunning: z.ZodOptional<z.ZodEnum<{
209
+ skip: "skip";
210
+ parallel: "parallel";
211
+ queue: "queue";
212
+ }>>;
203
213
  elementId: z.ZodOptional<z.ZodString>;
204
214
  preview: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
205
215
  }, z.core.$strip>, z.ZodObject<{
@@ -216,6 +226,8 @@ export declare const screenshotShape: {
216
226
  localStorage: "localStorage";
217
227
  sessionStorage: "sessionStorage";
218
228
  }>>;
229
+ transientState: z.ZodOptional<z.ZodArray<z.ZodString>>;
230
+ paintedState: z.ZodOptional<z.ZodArray<z.ZodString>>;
219
231
  userProvider: z.ZodOptional<z.ZodString>;
220
232
  tokenStorage: z.ZodOptional<z.ZodEnum<{
221
233
  "": "";
@@ -238,6 +250,21 @@ export declare const screenshotShape: {
238
250
  strict: "strict";
239
251
  }>>;
240
252
  sessionRevalidateSeconds: z.ZodOptional<z.ZodNumber>;
253
+ channels: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodObject<{
254
+ access: z.ZodObject<{
255
+ mode: z.ZodEnum<{
256
+ public: "public";
257
+ session: "session";
258
+ role: "role";
259
+ }>;
260
+ permissions: z.ZodOptional<z.ZodArray<z.ZodString>>;
261
+ }, z.core.$strip>;
262
+ publish: z.ZodOptional<z.ZodEnum<{
263
+ server: "server";
264
+ clients: "clients";
265
+ }>>;
266
+ presence: z.ZodOptional<z.ZodBoolean>;
267
+ }, z.core.$strip>>>>;
241
268
  }, z.core.$strip>, z.ZodObject<{
242
269
  desktop: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
243
270
  tablet: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>>;
@@ -990,6 +1017,13 @@ export declare const screenshotShape: {
990
1017
  }, z.core.$strip>, z.ZodObject<{
991
1018
  type: z.ZodLiteral<"deleteAction">;
992
1019
  ref: z.ZodString;
1020
+ }, z.core.$strip>, z.ZodObject<{
1021
+ type: z.ZodLiteral<"upsertFunctionFile">;
1022
+ path: z.ZodString;
1023
+ content: z.ZodString;
1024
+ }, z.core.$strip>, z.ZodObject<{
1025
+ type: z.ZodLiteral<"deleteFunctionFile">;
1026
+ path: z.ZodString;
993
1027
  }, z.core.$strip>], "type">>>;
994
1028
  viewport: z.ZodOptional<z.ZodEnum<{
995
1029
  desktop: "desktop";
@@ -997,5 +1031,10 @@ export declare const screenshotShape: {
997
1031
  both: "both";
998
1032
  }>>;
999
1033
  fullPage: z.ZodOptional<z.ZodBoolean>;
1034
+ view: z.ZodOptional<z.ZodEnum<{
1035
+ image: "image";
1036
+ accessibility: "accessibility";
1037
+ both: "both";
1038
+ }>>;
1000
1039
  };
1001
1040
  export declare const screenshotTool: import('.').ToolDef;