@plitzi/sdk-server 0.32.5 → 0.32.6

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 (168) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/core/services/mcp.js +1 -1
  3. package/dist/helpers/buildServerInfo.js +3 -9
  4. package/dist/index.js +2 -1
  5. package/dist/modules/mcp/catalogs/builtinCallbacks.js +204 -0
  6. package/dist/modules/mcp/catalogs/builtinComponents.js +170 -0
  7. package/dist/modules/mcp/catalogs/builtinElementCallbacks.js +50 -0
  8. package/dist/modules/mcp/catalogs/builtinTransformers.js +148 -0
  9. package/dist/modules/mcp/catalogs/builtinUtilities.js +90 -0
  10. package/dist/modules/mcp/{tools/operations/style → catalogs}/cssCatalog.js +75 -2
  11. package/dist/modules/mcp/catalogs/observed.js +90 -0
  12. package/dist/modules/mcp/catalogs/paramSpec.js +69 -0
  13. package/dist/modules/mcp/catalogs/registry.js +89 -0
  14. package/dist/modules/mcp/handler.js +12 -2
  15. package/dist/modules/mcp/helpers/agentPrompt.js +104 -0
  16. package/dist/modules/mcp/helpers/guide.js +334 -15
  17. package/dist/modules/mcp/helpers/interactions.js +123 -0
  18. package/dist/modules/mcp/helpers/log.js +54 -0
  19. package/dist/modules/mcp/helpers/space.js +158 -33
  20. package/dist/modules/mcp/helpers/uris.js +44 -0
  21. package/dist/modules/mcp/resources/canonical.js +6 -21
  22. package/dist/modules/mcp/resources/core.js +4 -3
  23. package/dist/modules/mcp/resources/primer.js +13 -8
  24. package/dist/modules/mcp/resources/register.js +37 -5
  25. package/dist/modules/mcp/resources/schema.js +30 -20
  26. package/dist/modules/mcp/resources/style.js +18 -11
  27. package/dist/modules/mcp/server.js +21 -7
  28. package/dist/modules/mcp/tools/apply/dispatch.js +38 -18
  29. package/dist/modules/mcp/tools/apply/index.js +19 -4
  30. package/dist/modules/mcp/tools/apply/writeResult.js +2 -1
  31. package/dist/modules/mcp/tools/index.js +1 -1
  32. package/dist/modules/mcp/tools/operations/index.js +13 -2
  33. package/dist/modules/mcp/tools/operations/schema/bindings/deleteBinding.js +32 -0
  34. package/dist/modules/mcp/tools/operations/schema/bindings/patchBinding.js +36 -0
  35. package/dist/modules/mcp/tools/operations/schema/bindings/upsertBinding.js +47 -0
  36. package/dist/modules/mcp/tools/operations/schema/{deleteElement.js → elements/deleteElement.js} +10 -6
  37. package/dist/modules/mcp/tools/operations/schema/{moveElement.js → elements/moveElement.js} +8 -6
  38. package/dist/modules/mcp/tools/operations/schema/{patchElement.js → elements/patchElement.js} +19 -7
  39. package/dist/modules/mcp/tools/operations/schema/{upsertElement.js → elements/upsertElement.js} +11 -5
  40. package/dist/modules/mcp/tools/operations/schema/{deleteFolder.js → folders/deleteFolder.js} +4 -4
  41. package/dist/modules/mcp/tools/operations/schema/{upsertFolder.js → folders/upsertFolder.js} +4 -4
  42. package/dist/modules/mcp/tools/operations/schema/interactions/deleteInteraction.js +52 -0
  43. package/dist/modules/mcp/tools/operations/schema/interactions/patchInteractionNode.js +47 -0
  44. package/dist/modules/mcp/tools/operations/schema/interactions/upsertInteractionFlow.js +43 -0
  45. package/dist/modules/mcp/tools/operations/schema/operations.js +25 -11
  46. package/dist/modules/mcp/tools/operations/schema/{deletePage.js → pages/deletePage.js} +8 -5
  47. package/dist/modules/mcp/tools/operations/schema/pages/upsertPage.js +75 -0
  48. package/dist/modules/mcp/tools/operations/schema/settings/patchSettings.js +45 -0
  49. package/dist/modules/mcp/tools/operations/schema/shared.js +94 -2
  50. package/dist/modules/mcp/tools/operations/schema/translator.js +77 -10
  51. package/dist/modules/mcp/tools/operations/schema/{deleteVariable.js → variables/deleteVariable.js} +3 -3
  52. package/dist/modules/mcp/tools/operations/schema/{upsertVariable.js → variables/upsertVariable.js} +4 -4
  53. package/dist/modules/mcp/tools/operations/schema/write.js +78 -13
  54. package/dist/modules/mcp/tools/operations/style/{deleteDefinition.js → definitions/deleteDefinition.js} +4 -3
  55. package/dist/modules/mcp/tools/operations/style/{patchDefinition.js → definitions/patchDefinition.js} +6 -5
  56. package/dist/modules/mcp/tools/operations/style/{upsertDefinition.js → definitions/upsertDefinition.js} +5 -4
  57. package/dist/modules/mcp/tools/operations/style/{deleteGlobalStyle.js → globalStyles/deleteGlobalStyle.js} +4 -3
  58. package/dist/modules/mcp/tools/operations/style/{patchGlobalStyle.js → globalStyles/patchGlobalStyle.js} +6 -5
  59. package/dist/modules/mcp/tools/operations/style/{upsertGlobalStyle.js → globalStyles/upsertGlobalStyle.js} +5 -4
  60. package/dist/modules/mcp/tools/operations/style/idStyles/deleteIdStyle.js +21 -0
  61. package/dist/modules/mcp/tools/operations/style/idStyles/patchIdStyle.js +28 -0
  62. package/dist/modules/mcp/tools/operations/style/idStyles/upsertIdStyle.js +24 -0
  63. package/dist/modules/mcp/tools/operations/style/operations.js +14 -8
  64. package/dist/modules/mcp/tools/operations/style/translator.js +25 -1
  65. package/dist/modules/mcp/tools/operations/style/{deleteStyleVariable.js → variables/deleteStyleVariable.js} +4 -4
  66. package/dist/modules/mcp/tools/operations/style/{upsertStyleVariable.js → variables/upsertStyleVariable.js} +4 -4
  67. package/dist/modules/mcp/tools/operations/style/write.js +19 -11
  68. package/dist/modules/mcp/tools/read.js +1 -1
  69. package/dist/modules/mcp/tools/search.js +34 -27
  70. package/dist/modules/mcp/tools/shared/validator/audit.js +124 -0
  71. package/dist/modules/mcp/tools/shared/validator/batch.js +30 -0
  72. package/dist/modules/mcp/tools/shared/validator/bindings.js +70 -0
  73. package/dist/modules/mcp/tools/shared/validator/context.js +35 -0
  74. package/dist/modules/mcp/tools/shared/validator/css.js +47 -0
  75. package/dist/modules/mcp/tools/shared/validator/elements.js +55 -0
  76. package/dist/modules/mcp/tools/shared/validator/index.js +226 -0
  77. package/dist/modules/mcp/tools/shared/validator/interactions.js +106 -0
  78. package/dist/modules/mcp/tools/shared/validator/refs.js +28 -0
  79. package/dist/modules/mcp/tools/validate.js +23 -3
  80. package/dist/modules/ssr/preview.js +1 -1
  81. package/dist/modules/ssr/views/template.ejs +2 -0
  82. package/dist/src/index.d.ts +1 -1
  83. package/dist/src/modules/mcp/catalogs/builtinCallbacks.d.ts +23 -0
  84. package/dist/src/modules/mcp/catalogs/builtinComponents.d.ts +4 -0
  85. package/dist/src/modules/mcp/catalogs/builtinElementCallbacks.d.ts +20 -0
  86. package/dist/src/modules/mcp/catalogs/builtinTransformers.d.ts +28 -0
  87. package/dist/src/modules/mcp/catalogs/builtinTransformers.test.d.ts +1 -0
  88. package/dist/src/modules/mcp/catalogs/builtinUtilities.d.ts +18 -0
  89. package/dist/src/modules/mcp/{tools/operations/style → catalogs}/cssCatalog.d.ts +5 -1
  90. package/dist/src/modules/mcp/catalogs/index.d.ts +9 -0
  91. package/dist/src/modules/mcp/catalogs/observed.d.ts +48 -0
  92. package/dist/src/modules/mcp/catalogs/paramSpec.d.ts +42 -0
  93. package/dist/src/modules/mcp/catalogs/registry.d.ts +35 -0
  94. package/dist/src/modules/mcp/handler.d.ts +2 -2
  95. package/dist/src/modules/mcp/helpers/agentPrompt.d.ts +4 -0
  96. package/dist/src/modules/mcp/helpers/guide.d.ts +2 -1
  97. package/dist/src/modules/mcp/helpers/index.d.ts +4 -0
  98. package/dist/src/modules/mcp/helpers/interactions.d.ts +30 -0
  99. package/dist/src/modules/mcp/helpers/log.d.ts +8 -0
  100. package/dist/src/modules/mcp/helpers/log.test.d.ts +1 -0
  101. package/dist/src/modules/mcp/helpers/space.d.ts +67 -11
  102. package/dist/src/modules/mcp/helpers/uris.d.ts +28 -0
  103. package/dist/src/modules/mcp/index.d.ts +1 -1
  104. package/dist/src/modules/mcp/mcp.bench.d.ts +1 -0
  105. package/dist/src/modules/mcp/resources/canonical.d.ts +0 -1
  106. package/dist/src/modules/mcp/resources/index.d.ts +2 -3
  107. package/dist/src/modules/mcp/resources/primer.d.ts +2 -1
  108. package/dist/src/modules/mcp/resources/register.d.ts +2 -2
  109. package/dist/src/modules/mcp/server.d.ts +5 -2
  110. package/dist/src/modules/mcp/tools/apply/index.d.ts +191 -2
  111. package/dist/src/modules/mcp/tools/operations/index.d.ts +383 -4
  112. package/dist/src/modules/mcp/tools/operations/schema/bindings/deleteBinding.d.ts +17 -0
  113. package/dist/src/modules/mcp/tools/operations/schema/bindings/patchBinding.d.ts +25 -0
  114. package/dist/src/modules/mcp/tools/operations/schema/bindings/upsertBinding.d.ts +27 -0
  115. package/dist/src/modules/mcp/tools/operations/schema/{deleteElement.d.ts → elements/deleteElement.d.ts} +2 -2
  116. package/dist/src/modules/mcp/tools/operations/schema/{moveElement.d.ts → elements/moveElement.d.ts} +2 -2
  117. package/dist/src/modules/mcp/tools/operations/schema/{patchElement.d.ts → elements/patchElement.d.ts} +7 -2
  118. package/dist/src/modules/mcp/tools/operations/schema/{upsertElement.d.ts → elements/upsertElement.d.ts} +3 -3
  119. package/dist/src/modules/mcp/tools/operations/schema/{deleteFolder.d.ts → folders/deleteFolder.d.ts} +2 -2
  120. package/dist/src/modules/mcp/tools/operations/schema/{upsertFolder.d.ts → folders/upsertFolder.d.ts} +2 -2
  121. package/dist/src/modules/mcp/tools/operations/schema/index.d.ts +17 -11
  122. package/dist/src/modules/mcp/tools/operations/schema/interactions/deleteInteraction.d.ts +12 -0
  123. package/dist/src/modules/mcp/tools/operations/schema/interactions/patchInteractionNode.d.ts +18 -0
  124. package/dist/src/modules/mcp/tools/operations/schema/interactions/upsertInteractionFlow.d.ts +27 -0
  125. package/dist/src/modules/mcp/tools/operations/schema/operations.d.ts +131 -0
  126. package/dist/src/modules/mcp/tools/operations/schema/{deletePage.d.ts → pages/deletePage.d.ts} +2 -2
  127. package/dist/src/modules/mcp/tools/operations/schema/{upsertPage.d.ts → pages/upsertPage.d.ts} +3 -2
  128. package/dist/src/modules/mcp/tools/operations/schema/settings/patchSettings.d.ts +34 -0
  129. package/dist/src/modules/mcp/tools/operations/schema/shared.d.ts +53 -0
  130. package/dist/src/modules/mcp/tools/operations/schema/translator.d.ts +5 -2
  131. package/dist/src/modules/mcp/tools/operations/schema/{deleteVariable.d.ts → variables/deleteVariable.d.ts} +2 -2
  132. package/dist/src/modules/mcp/tools/operations/schema/{upsertVariable.d.ts → variables/upsertVariable.d.ts} +2 -2
  133. package/dist/src/modules/mcp/tools/operations/schema/write.d.ts +38 -8
  134. package/dist/src/modules/mcp/tools/operations/style/{deleteDefinition.d.ts → definitions/deleteDefinition.d.ts} +2 -2
  135. package/dist/src/modules/mcp/tools/operations/style/{patchDefinition.d.ts → definitions/patchDefinition.d.ts} +2 -2
  136. package/dist/src/modules/mcp/tools/operations/style/{upsertDefinition.d.ts → definitions/upsertDefinition.d.ts} +2 -2
  137. package/dist/src/modules/mcp/tools/operations/style/{deleteGlobalStyle.d.ts → globalStyles/deleteGlobalStyle.d.ts} +2 -2
  138. package/dist/src/modules/mcp/tools/operations/style/{patchGlobalStyle.d.ts → globalStyles/patchGlobalStyle.d.ts} +2 -2
  139. package/dist/src/modules/mcp/tools/operations/style/{upsertGlobalStyle.d.ts → globalStyles/upsertGlobalStyle.d.ts} +2 -2
  140. package/dist/src/modules/mcp/tools/operations/style/idStyles/deleteIdStyle.d.ts +9 -0
  141. package/dist/src/modules/mcp/tools/operations/style/idStyles/patchIdStyle.d.ts +37 -0
  142. package/dist/src/modules/mcp/tools/operations/style/idStyles/upsertIdStyle.d.ts +37 -0
  143. package/dist/src/modules/mcp/tools/operations/style/index.d.ts +11 -9
  144. package/dist/src/modules/mcp/tools/operations/style/operations.d.ts +70 -2
  145. package/dist/src/modules/mcp/tools/operations/style/shared.d.ts +1 -1
  146. package/dist/src/modules/mcp/tools/operations/style/translator.d.ts +4 -1
  147. package/dist/src/modules/mcp/tools/operations/style/{deleteStyleVariable.d.ts → variables/deleteStyleVariable.d.ts} +3 -3
  148. package/dist/src/modules/mcp/tools/operations/style/{upsertStyleVariable.d.ts → variables/upsertStyleVariable.d.ts} +3 -3
  149. package/dist/src/modules/mcp/tools/operations/style/write.d.ts +2 -7
  150. package/dist/src/modules/mcp/tools/preview.d.ts +191 -2
  151. package/dist/src/modules/mcp/tools/screenshot.d.ts +191 -2
  152. package/dist/src/modules/mcp/tools/shared/validator/audit.d.ts +4 -0
  153. package/dist/src/modules/mcp/tools/shared/validator/batch.d.ts +5 -0
  154. package/dist/src/modules/mcp/tools/shared/validator/bindings.d.ts +6 -0
  155. package/dist/src/modules/mcp/tools/shared/validator/context.d.ts +34 -0
  156. package/dist/src/modules/mcp/tools/shared/validator/css.d.ts +4 -0
  157. package/dist/src/modules/mcp/tools/shared/validator/elements.d.ts +6 -0
  158. package/dist/src/modules/mcp/tools/shared/validator/index.d.ts +8 -0
  159. package/dist/src/modules/mcp/tools/shared/validator/interactions.d.ts +3 -0
  160. package/dist/src/modules/mcp/tools/shared/validator/refs.d.ts +4 -0
  161. package/dist/src/modules/mcp/tools/validate.d.ts +191 -2
  162. package/dist/src/modules/mcp/types/aiSchema.d.ts +93 -1
  163. package/package.json +12 -10
  164. package/dist/modules/mcp/tools/operations/schema/registry.js +0 -55
  165. package/dist/modules/mcp/tools/operations/schema/upsertPage.js +0 -64
  166. package/dist/modules/mcp/tools/shared/validator.js +0 -262
  167. package/dist/src/modules/mcp/tools/operations/schema/registry.d.ts +0 -22
  168. package/dist/src/modules/mcp/tools/shared/validator.d.ts +0 -4
@@ -1,13 +1,20 @@
1
- import { deleteElementOp } from "./deleteElement.js";
2
- import { deleteFolderOp } from "./deleteFolder.js";
3
- import { deletePageOp } from "./deletePage.js";
4
- import { deleteVariableOp } from "./deleteVariable.js";
5
- import { moveElementOp } from "./moveElement.js";
6
- import { patchElementOp } from "./patchElement.js";
7
- import { upsertElementOp } from "./upsertElement.js";
8
- import { upsertFolderOp } from "./upsertFolder.js";
9
- import { upsertPageOp } from "./upsertPage.js";
10
- import { upsertVariableOp } from "./upsertVariable.js";
1
+ import { deleteBindingOp } from "./bindings/deleteBinding.js";
2
+ import { patchBindingOp } from "./bindings/patchBinding.js";
3
+ import { upsertBindingOp } from "./bindings/upsertBinding.js";
4
+ import { deleteElementOp } from "./elements/deleteElement.js";
5
+ import { moveElementOp } from "./elements/moveElement.js";
6
+ import { patchElementOp } from "./elements/patchElement.js";
7
+ import { upsertElementOp } from "./elements/upsertElement.js";
8
+ import { deleteFolderOp } from "./folders/deleteFolder.js";
9
+ import { upsertFolderOp } from "./folders/upsertFolder.js";
10
+ import { deleteInteractionOp } from "./interactions/deleteInteraction.js";
11
+ import { patchInteractionNodeOp } from "./interactions/patchInteractionNode.js";
12
+ import { upsertInteractionFlowOp } from "./interactions/upsertInteractionFlow.js";
13
+ import { deletePageOp } from "./pages/deletePage.js";
14
+ import { upsertPageOp } from "./pages/upsertPage.js";
15
+ import { patchSettingsOp } from "./settings/patchSettings.js";
16
+ import { deleteVariableOp } from "./variables/deleteVariable.js";
17
+ import { upsertVariableOp } from "./variables/upsertVariable.js";
11
18
  //#region src/modules/mcp/tools/operations/schema/operations.ts
12
19
  var elementOps = {
13
20
  upsertElement: upsertElementOp,
@@ -19,7 +26,14 @@ var elementOps = {
19
26
  upsertFolder: upsertFolderOp,
20
27
  deleteFolder: deleteFolderOp,
21
28
  upsertVariable: upsertVariableOp,
22
- deleteVariable: deleteVariableOp
29
+ deleteVariable: deleteVariableOp,
30
+ upsertBinding: upsertBindingOp,
31
+ patchBinding: patchBindingOp,
32
+ deleteBinding: deleteBindingOp,
33
+ upsertInteractionFlow: upsertInteractionFlowOp,
34
+ patchInteractionNode: patchInteractionNodeOp,
35
+ deleteInteraction: deleteInteractionOp,
36
+ patchSettings: patchSettingsOp
23
37
  };
24
38
  //#endregion
25
39
  export { elementOps };
@@ -1,8 +1,8 @@
1
- import { descendantIds, findPageByRef } from "../../../helpers/space.js";
2
- import { empty, fail } from "../../../helpers/opResult.js";
3
- import { pageUri, pagesUri } from "./write.js";
1
+ import { descendantIds, findPageByRef, indexRemovePage } from "../../../../helpers/space.js";
2
+ import { pageUri, pagesUri } from "../../../../helpers/uris.js";
3
+ import { empty, fail } from "../../../../helpers/opResult.js";
4
4
  import { z } from "zod";
5
- //#region src/modules/mcp/tools/operations/schema/deletePage.ts
5
+ //#region src/modules/mcp/tools/operations/schema/pages/deletePage.ts
6
6
  var deletePageOp = z.object({
7
7
  type: z.literal("deletePage"),
8
8
  ref: z.string().describe("Page ref or id")
@@ -10,8 +10,11 @@ var deletePageOp = z.object({
10
10
  var deletePage = (space, env, op) => {
11
11
  const page = findPageByRef(space.schema, op.ref);
12
12
  if (!page) return fail("ref", `Page "${op.ref}" not found`, "Read the pages resource for valid refs");
13
- for (const id of [...descendantIds(space.schema, page.id), page.id]) Reflect.deleteProperty(space.schema.flat, id);
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
16
  space.schema.pages = space.schema.pages.filter((id) => id !== page.id);
17
+ indexRemovePage(space.schema, page, descendants);
15
18
  return {
16
19
  ...empty(),
17
20
  deleted: 1,
@@ -0,0 +1,75 @@
1
+ import { findFolderByRef, findPageByRef, generateObjectId, indexAddPage, indexReRefPage, pageRefOf } from "../../../../helpers/space.js";
2
+ import { pageUri, pagesUri } from "../../../../helpers/uris.js";
3
+ import { empty, fail } from "../../../../helpers/opResult.js";
4
+ import { guardNewRef } from "../write.js";
5
+ import { z } from "zod";
6
+ //#region src/modules/mcp/tools/operations/schema/pages/upsertPage.ts
7
+ var upsertPageOp = z.object({
8
+ type: z.literal("upsertPage"),
9
+ ref: z.string().describe("Page id/slug to update, or a new id you choose to create one. On a new page it is stored as its idRef: starts with a letter, then letters, numbers, hyphens and underscores (\"pricing\"), unique across the space."),
10
+ label: z.string().optional(),
11
+ slug: z.string().optional().describe("The page URL path, RELATIVE — do NOT start it with \"/\" (the runtime and any parent folder slugs prepend the path; a leading \"/\" is stripped). Good practice: always set one on create for a clean, stable route, e.g. \"pricing\" or \"posts/:postId\" (a \":name\" segment is a route param, readable as {{name}} and as the source navigation.routeParams.name). Omitted on create → the page ref is used as the slug."),
12
+ folder: z.string().nullable().optional().describe("Ref of an existing folder to place this page in; \"\" or null moves it to the root. Unknown → error"),
13
+ default: z.boolean().optional(),
14
+ enabled: z.boolean().optional().describe("false disables the page in the published SDK runtime (not routable/accessible to end users); it stays editable here. Defaults to true")
15
+ }).describe("Create a page, or update it when ref already exists (only the fields you pass change).");
16
+ var upsertPage = (space, env, op) => {
17
+ const slug = op.slug === void 0 ? void 0 : op.slug.replace(/^\/+/, "");
18
+ let folderValue;
19
+ if (op.folder !== void 0) if (op.folder === null || op.folder === "") folderValue = "";
20
+ else {
21
+ const resolved = findFolderByRef(space.schema, op.folder);
22
+ if (!resolved) return fail("folder", `Folder "${op.folder}" not found`, "Create it with upsertFolder, or read plitzi://folders");
23
+ folderValue = resolved.id;
24
+ }
25
+ const existing = findPageByRef(space.schema, op.ref);
26
+ if (existing) {
27
+ const oldRef = pageRefOf(existing);
28
+ existing.attributes = {
29
+ ...existing.attributes,
30
+ ...slug !== void 0 ? { slug } : {},
31
+ ...op.label !== void 0 ? { name: op.label } : {},
32
+ ...op.default !== void 0 ? { default: op.default } : {},
33
+ ...op.enabled !== void 0 ? { enabled: op.enabled } : {},
34
+ ...folderValue !== void 0 ? { folder: folderValue } : {}
35
+ };
36
+ indexReRefPage(space.schema, existing, oldRef);
37
+ return {
38
+ ...empty(),
39
+ updated: 1,
40
+ staleResources: [pageUri(env, op.ref), pagesUri(env)]
41
+ };
42
+ }
43
+ const guard = guardNewRef(space, op.ref, "ref");
44
+ if (guard) return guard;
45
+ const id = generateObjectId();
46
+ const attributes = {
47
+ slug: slug ?? op.ref,
48
+ name: op.label ?? op.ref,
49
+ default: op.default ?? false,
50
+ enabled: op.enabled ?? true,
51
+ folder: folderValue ?? ""
52
+ };
53
+ const page = {
54
+ id,
55
+ idRef: op.ref,
56
+ attributes,
57
+ definition: {
58
+ rootId: id,
59
+ label: op.label ?? op.ref,
60
+ type: "page",
61
+ items: [],
62
+ styleSelectors: { base: "" }
63
+ }
64
+ };
65
+ space.schema.flat[id] = page;
66
+ space.schema.pages.push(id);
67
+ indexAddPage(space.schema, page);
68
+ return {
69
+ ...empty(),
70
+ created: 1,
71
+ staleResources: [pageUri(env, op.ref), pagesUri(env)]
72
+ };
73
+ };
74
+ //#endregion
75
+ export { upsertPage, upsertPageOp };
@@ -0,0 +1,45 @@
1
+ import { settingsUri } from "../../../../helpers/uris.js";
2
+ import { empty } from "../../../../helpers/opResult.js";
3
+ import { z } from "zod";
4
+ //#region src/modules/mcp/tools/operations/schema/settings/patchSettings.ts
5
+ var userProvider = z.enum([
6
+ "auth0",
7
+ "basic",
8
+ "custom",
9
+ ""
10
+ ]);
11
+ var storage = z.enum([
12
+ "localStorage",
13
+ "sessionStorage",
14
+ ""
15
+ ]);
16
+ var patchSettingsOp = z.object({
17
+ type: z.literal("patchSettings"),
18
+ customCss: z.string().optional().describe("Raw global CSS for the whole space (keyframes, @font-face, resets)"),
19
+ keepState: z.boolean().optional().describe("Persist element state across reloads"),
20
+ stateStorage: z.enum(["localStorage", "sessionStorage"]).optional(),
21
+ userProvider: userProvider.optional().describe("Auth provider; \"\" disables authentication"),
22
+ auth0Domain: z.string().optional(),
23
+ auth0ClientId: z.string().optional(),
24
+ tokenStorage: storage.optional(),
25
+ loginUrl: z.string().optional(),
26
+ userUrl: z.string().optional(),
27
+ refreshUrl: z.string().optional(),
28
+ logoutUrl: z.string().optional(),
29
+ detailsPath: z.string().optional(),
30
+ tokenPath: z.string().optional(),
31
+ expirationTimePath: z.string().optional()
32
+ }).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).");
33
+ var patchSettings = (space, env, op) => {
34
+ const { type, ...patch } = op;
35
+ const next = { ...space.schema.settings };
36
+ for (const [key, value] of Object.entries(patch)) next[key] = value;
37
+ space.schema.settings = next;
38
+ return {
39
+ ...empty(),
40
+ updated: 1,
41
+ staleResources: [settingsUri(env)]
42
+ };
43
+ };
44
+ //#endregion
45
+ export { patchSettings, patchSettingsOp };
@@ -1,16 +1,73 @@
1
1
  import { z } from "zod";
2
2
  //#region src/modules/mcp/tools/operations/schema/shared.ts
3
+ var combinator = z.enum(["and", "or"]);
4
+ var operator = z.enum([
5
+ "",
6
+ "=",
7
+ "!=",
8
+ "<",
9
+ ">",
10
+ "<=",
11
+ ">=",
12
+ "contains",
13
+ "doesNotContain",
14
+ "beginsWith",
15
+ "doesNotBeginWith",
16
+ "endsWith",
17
+ "doesNotEndWith",
18
+ "empty",
19
+ "notEmpty",
20
+ "in",
21
+ "notIn",
22
+ "between",
23
+ "notBetween"
24
+ ]);
25
+ var ruleValue = z.union([
26
+ z.string(),
27
+ z.number(),
28
+ z.boolean(),
29
+ z.null(),
30
+ z.record(z.string(), z.unknown()),
31
+ z.array(z.unknown())
32
+ ]);
33
+ var ruleBase = {
34
+ id: z.string().optional(),
35
+ field: z.string().describe("The data field the rule tests"),
36
+ operator,
37
+ enabled: z.boolean().optional()
38
+ };
39
+ var rule = z.union([z.object({
40
+ ...ruleBase,
41
+ isBinding: z.literal(true),
42
+ value: z.string()
43
+ }), z.object({
44
+ ...ruleBase,
45
+ isBinding: z.literal(false).optional(),
46
+ value: ruleValue
47
+ })]);
48
+ var ruleGroup = z.lazy(() => z.object({
49
+ id: z.string().optional(),
50
+ combinator,
51
+ rules: z.array(z.union([rule, ruleGroup])),
52
+ enabled: z.boolean().optional()
53
+ }));
3
54
  var styleRefs = z.object({
4
55
  base: z.array(z.string()).optional(),
5
56
  slots: z.record(z.string(), z.array(z.string())).optional()
6
57
  });
58
+ var styleVariantInput = z.record(z.string(), z.record(z.string(), z.union([z.string(), z.array(z.string())])));
59
+ var initialStateInput = z.object({
60
+ styleVariant: styleVariantInput.optional().describe("Variant each attached class uses: { className: { base|slot: variantName | [names] } }"),
61
+ visibility: z.boolean().optional().describe("Initial visibility of the element")
62
+ });
7
63
  var elementInput = z.lazy(() => z.object({
8
- ref: z.string().describe("Semantic id you choose, or an existing element ref/id"),
64
+ ref: z.string().describe("Semantic id you choose, or an existing element ref/id. On a new element this is stored as its idRef and becomes the key everything else addresses it by — its data source is named `<type>_<ref>`, and an interaction targets it by this ref. Start with a letter, then letters, numbers, hyphens and underscores (\"hero-cta\" or \"food_item\"): a dot would break the `<type>_<idRef>.<field>` grammar (an underscore is fine — the first `_` separates the type from the idRef). Must be unique across the space."),
9
65
  type: z.string().describe("Type from plitzi://types"),
10
66
  label: z.string().optional(),
11
67
  subType: z.string().optional(),
12
68
  props: z.record(z.string(), z.unknown()).optional().describe("Full replacement on update"),
13
69
  style: styleRefs.optional().describe("Definition refs per slot; style the element by attaching a definition"),
70
+ initialState: initialStateInput.optional().describe("Applied style variant(s) and initial visibility (see plitzi://guide styling)"),
14
71
  children: z.array(elementInput).optional()
15
72
  }));
16
73
  var position = z.enum([
@@ -23,5 +80,40 @@ var scalar = z.union([
23
80
  z.number(),
24
81
  z.boolean()
25
82
  ]);
83
+ var bindingCategory = z.enum([
84
+ "attributes",
85
+ "style",
86
+ "initialState"
87
+ ]).describe("What the value feeds: a prop (attributes), a style value (style), or an initialState key");
88
+ var bindingTransformer = z.object({
89
+ action: z.string().describe("Transformer action name"),
90
+ params: z.record(z.string(), z.string()),
91
+ enabled: z.boolean().optional().describe("Set false to keep the transformer in the chain but skip it at runtime (defaults to true)")
92
+ });
93
+ var bindingInput = z.object({
94
+ to: z.string().describe("Target field the value feeds (a prop key, style value, or initialState key)"),
95
+ source: z.string().describe("Data source path, e.g. \"apiContainer_x.data\" — see plitzi://data-sources"),
96
+ id: z.string().optional().describe("Stable binding id; generated when omitted"),
97
+ transformers: z.array(bindingTransformer).optional(),
98
+ when: ruleGroup.optional().describe("QueryBuilder RuleGroup gating the binding (validated structurally)"),
99
+ enabled: z.boolean().optional()
100
+ });
101
+ var interactionNodeType = z.enum([
102
+ "trigger",
103
+ "globalCallback",
104
+ "callback",
105
+ "utility"
106
+ ]).describe("trigger starts a flow (must be first); the rest run in order after it");
107
+ var interactionNode = z.object({
108
+ id: z.string().optional().describe("Existing node id to preserve; generated when omitted"),
109
+ title: z.string().describe("Human label for the step"),
110
+ nodeType: interactionNodeType,
111
+ action: z.string().describe("Action name, e.g. \"onClick\", \"login\" — see plitzi://interactions"),
112
+ params: z.record(z.string(), z.unknown()).optional(),
113
+ enabled: z.boolean().optional(),
114
+ when: ruleGroup.optional().describe("QueryBuilder RuleGroup gating this step (validated structurally)"),
115
+ elementId: z.string().optional().describe("Element whose callback this step invokes; defaults to this element. Give its ref or its raw id — a raw id is normalised to the element idRef the runtime looks callbacks up by, and a target without an idRef is given one automatically."),
116
+ preview: z.record(z.string(), z.unknown()).optional()
117
+ });
26
118
  //#endregion
27
- export { elementInput, position, scalar, styleRefs };
119
+ export { bindingCategory, bindingInput, elementInput, initialStateInput, interactionNode, interactionNodeType, position, ruleGroup, scalar, styleRefs, styleVariantInput };
@@ -1,9 +1,9 @@
1
- import { descendantCount, descendantIds, elementById, elementRefOf, getPageElements, isPageElement, orderedChildren, pageFoldersOf, pageRefOf, pageRefOfElement, slugRouteParams } from "../../../helpers/space.js";
2
- import { definitionToAI, globalStylesForType } from "../style/translator.js";
1
+ import { computeVersion } from "../../../helpers/computeVersion.js";
2
+ import { descendantCount, descendantIds, elementById, elementRefOf, getPageElements, isPageElement, nameOf, orderedChildren, pageFoldersOf, pageRefOf, pageRefOfElement, slugRouteParams, spaceIndex, strOr } from "../../../helpers/space.js";
3
+ import { bindingsToAI, flowsFromInteractions } from "../../../helpers/interactions.js";
4
+ import { definitionToAI, globalStylesForType, idStyleToAI } from "../style/translator.js";
3
5
  //#region src/modules/mcp/tools/operations/schema/translator.ts
4
6
  var splitClasses = (value) => value ? value.split(/\s+/).filter(Boolean) : [];
5
- var strOr = (value) => typeof value === "string" ? value : void 0;
6
- var nameOf = (page) => strOr(page.attributes.name) ?? page.definition.label;
7
7
  var propsOf = (el) => {
8
8
  const { subType, ...rest } = el.attributes;
9
9
  return Object.keys(rest).length > 0 ? rest : void 0;
@@ -18,6 +18,7 @@ var pageSummariesToAI = (schema) => getPageElements(schema).map((page) => ({
18
18
  label: nameOf(page),
19
19
  slug: strOr(page.attributes.slug) ?? "",
20
20
  default: page.attributes.default === true,
21
+ enabled: page.attributes.enabled !== false,
21
22
  folder: strOr(page.attributes.folder) || void 0,
22
23
  elementCount: descendantCount(schema, page.id)
23
24
  }));
@@ -32,7 +33,20 @@ var folderRefToAI = (schema, ref) => {
32
33
  const folder = pageFoldersOf(schema).find((f) => f.id === ref);
33
34
  return folder ? folderToAI(folder) : void 0;
34
35
  };
35
- var skeletonNode = (schema, el) => {
36
+ var elementView = (schema, el, style) => {
37
+ const cache = spaceIndex(schema).detailCache;
38
+ const cached = cache.get(el.id);
39
+ if (cached && cached.style === style) return cached;
40
+ const detail = elementDetailToAI(schema, el, style);
41
+ const view = {
42
+ style,
43
+ detail,
44
+ version: computeVersion(detail)
45
+ };
46
+ cache.set(el.id, view);
47
+ return view;
48
+ };
49
+ var skeletonNode = (schema, el, style) => {
36
50
  const children = orderedChildren(schema, el);
37
51
  const base = splitClasses(el.definition.styleSelectors.base);
38
52
  const slots = slotClasses(el.definition.styleSelectors);
@@ -41,21 +55,23 @@ var skeletonNode = (schema, el) => {
41
55
  type: el.definition.type,
42
56
  label: el.definition.label,
43
57
  subType: strOr(el.attributes.subType),
58
+ stateVersion: style ? elementView(schema, el, style).version : void 0,
44
59
  base: base.length > 0 ? base : void 0,
45
60
  slots: Object.keys(slots).length > 0 ? slots : void 0,
46
61
  childCount: children.length,
47
- children: children.length > 0 ? children.map((child) => skeletonNode(schema, child)) : void 0
62
+ children: children.length > 0 ? children.map((child) => skeletonNode(schema, child, style)) : void 0
48
63
  };
49
64
  };
50
- var pageSkeletonToAI = (schema, pageEl) => {
65
+ var pageSkeletonToAI = (schema, pageEl, style) => {
51
66
  const slug = strOr(pageEl.attributes.slug) ?? "";
52
67
  return {
53
68
  ref: pageRefOf(pageEl),
54
69
  label: nameOf(pageEl),
55
70
  slug,
56
71
  default: pageEl.attributes.default === true,
72
+ enabled: pageEl.attributes.enabled !== false,
57
73
  routeParams: slugRouteParams(slug),
58
- tree: orderedChildren(schema, pageEl).map((child) => skeletonNode(schema, child))
74
+ tree: orderedChildren(schema, pageEl).map((child) => skeletonNode(schema, child, style))
59
75
  };
60
76
  };
61
77
  var elementClassRefs = (el) => {
@@ -102,6 +118,37 @@ var resolveDefinitions = (style, base, slots) => {
102
118
  }
103
119
  return Object.keys(resolved).length > 0 ? resolved : void 0;
104
120
  };
121
+ var variantNamesOf = (def) => {
122
+ const names = new Set(Object.keys(def.variants ?? {}));
123
+ for (const slot of Object.values(def.slots ?? {})) for (const name of Object.keys(slot.variants ?? {})) names.add(name);
124
+ return [...names].sort();
125
+ };
126
+ var availableVariantsFrom = (resolvedStyle) => {
127
+ if (!resolvedStyle) return;
128
+ const result = {};
129
+ for (const [ref, def] of Object.entries(resolvedStyle)) {
130
+ const names = variantNamesOf(def);
131
+ if (names.length > 0) result[ref] = names;
132
+ }
133
+ return Object.keys(result).length > 0 ? result : void 0;
134
+ };
135
+ var initialStateToAI = (el) => {
136
+ const initialState = el.definition.initialState;
137
+ if (!initialState) return;
138
+ const result = {};
139
+ if (initialState.styleVariant) {
140
+ const styleVariant = {};
141
+ for (const [cls, selectors] of Object.entries(initialState.styleVariant)) {
142
+ if (!selectors) continue;
143
+ const bySelector = {};
144
+ for (const [selector, variant] of Object.entries(selectors)) if (variant !== void 0) bySelector[selector] = variant;
145
+ if (Object.keys(bySelector).length > 0) styleVariant[cls] = bySelector;
146
+ }
147
+ if (Object.keys(styleVariant).length > 0) result.styleVariant = styleVariant;
148
+ }
149
+ if (typeof initialState.visibility === "boolean") result.visibility = initialState.visibility;
150
+ return Object.keys(result).length > 0 ? result : void 0;
151
+ };
105
152
  var elementDetailToAI = (schema, el, style) => {
106
153
  const children = orderedChildren(schema, el);
107
154
  const parent = el.definition.parentId ? schema.flat[el.definition.parentId] : void 0;
@@ -121,11 +168,26 @@ var elementDetailToAI = (schema, el, style) => {
121
168
  },
122
169
  childRefs: children.length > 0 ? children.map(elementRefOf) : void 0
123
170
  };
171
+ const initialState = initialStateToAI(el);
172
+ if (initialState) detail.initialState = initialState;
173
+ const bindings = bindingsToAI(el.definition.bindings);
174
+ if (bindings) detail.bindings = bindings;
175
+ const interactions = flowsFromInteractions(el.definition.interactions);
176
+ if (interactions.length > 0) detail.interactions = interactions;
124
177
  if (style) {
125
178
  const resolvedStyle = resolveDefinitions(style, base, slots);
126
- if (resolvedStyle) detail.resolvedStyle = resolvedStyle;
179
+ if (resolvedStyle) {
180
+ detail.resolvedStyle = resolvedStyle;
181
+ const availableVariants = availableVariantsFrom(resolvedStyle);
182
+ if (availableVariants) detail.availableVariants = availableVariants;
183
+ }
127
184
  const globalStyles = globalStylesForType(style, el.definition.type);
128
185
  if (globalStyles.length > 0) detail.globalStyles = globalStyles;
186
+ const domId = strOr(el.attributes.id);
187
+ if (domId) {
188
+ const idStyle = idStyleToAI(style, domId);
189
+ if (idStyle) detail.idStyle = idStyle;
190
+ }
129
191
  }
130
192
  return detail;
131
193
  };
@@ -144,5 +206,10 @@ var schemaVariablesToAI = (schema, includeSubValues = true) => {
144
206
  };
145
207
  return data;
146
208
  };
209
+ var settingsToAI = (schema) => {
210
+ const result = {};
211
+ for (const [key, value] of Object.entries(schema.settings)) result[key] = value;
212
+ return result;
213
+ };
147
214
  //#endregion
148
- export { elementDetailToAI, folderRefToAI, foldersToAI, pageSkeletonToAI, pageStylesToAI, pageSummariesToAI, schemaVariablesToAI };
215
+ export { elementDetailToAI, elementView, folderRefToAI, foldersToAI, pageSkeletonToAI, pageStylesToAI, pageSummariesToAI, schemaVariablesToAI, settingsToAI };
@@ -1,7 +1,7 @@
1
- import { empty } from "../../../helpers/opResult.js";
2
- import { schemaVarsUri } from "./write.js";
1
+ import { schemaVarsUri } from "../../../../helpers/uris.js";
2
+ import { empty } from "../../../../helpers/opResult.js";
3
3
  import { z } from "zod";
4
- //#region src/modules/mcp/tools/operations/schema/deleteVariable.ts
4
+ //#region src/modules/mcp/tools/operations/schema/variables/deleteVariable.ts
5
5
  var deleteVariableOp = z.object({
6
6
  type: z.literal("deleteVariable"),
7
7
  name: z.string().describe("Name of the schema variable to delete")
@@ -1,8 +1,8 @@
1
- import { empty } from "../../../helpers/opResult.js";
2
- import { schemaVarsUri } from "./write.js";
3
- import { scalar } from "./shared.js";
1
+ import { schemaVarsUri } from "../../../../helpers/uris.js";
2
+ import { empty } from "../../../../helpers/opResult.js";
3
+ import { scalar } from "../shared.js";
4
4
  import { z } from "zod";
5
- //#region src/modules/mcp/tools/operations/schema/upsertVariable.ts
5
+ //#region src/modules/mcp/tools/operations/schema/variables/upsertVariable.ts
6
6
  var upsertVariableOp = z.object({
7
7
  type: z.literal("upsertVariable"),
8
8
  name: z.string().describe("Variable name; referenced in content as {{name}}"),
@@ -1,18 +1,51 @@
1
- import { generateObjectId } from "../../../helpers/space.js";
1
+ import { findElementByRef, findPageByRef, generateObjectId, indexAddElement, indexReRefElement, resolveRef, spaceIndex } from "../../../helpers/space.js";
2
+ import { folderUri, foldersUri, pageUri, pagesUri, schemaVarsUri, settingsUri } from "../../../helpers/uris.js";
3
+ import { fail } from "../../../helpers/opResult.js";
4
+ import { isValidIdRef, makeIdRef } from "@plitzi/sdk-schema/helpers/idRef";
2
5
  //#region src/modules/mcp/tools/operations/schema/write.ts
3
- var pageUri = (env, ref) => `plitzi://schema/${env}/pages/${ref}`;
4
- var pagesUri = (env) => `plitzi://schema/${env}/pages`;
5
- var foldersUri = (env) => `plitzi://folders/${env}`;
6
- var folderUri = (env, ref) => `plitzi://folders/${env}/${ref}`;
7
- var schemaVarsUri = (env) => `plitzi://schema-variables/${env}`;
8
- var removeFromParent = (space, childId) => {
9
- for (const el of Object.values(space.schema.flat)) if (el.definition.items?.includes(childId)) el.definition.items = el.definition.items.filter((id) => id !== childId);
6
+ var ID_REF_HINT = "Start with a letter, then letters, numbers, hyphens and underscores (e.g. \"hero-cta\" or \"food_item\"). The ref becomes the element idRef, which the runtime embeds in source names like `apiContainer_<idRef>.field` and in interaction targets — a dot would split those paths (an underscore is fine: the FIRST `_` separates the type from the idRef, and element types carry none, so extra underscores are unambiguous).";
7
+ var TAKEN_HINT = "An idRef must be unique across the space — pick a different ref, or address the existing element by this ref.";
8
+ /** Every ref in an element input tree (the element plus its nested children) each becomes a new element's idRef. */
9
+ var collectInputRefs = (input) => [input.ref, ...(input.children ?? []).flatMap(collectInputRefs)];
10
+ /** Validate a ref that is about to become an element's idRef: the charset, then whether anything already answers
11
+ * to it. The charset rule is sdk-schema's `isValidIdRef` — never a regex restated here, so the MCP cannot drift
12
+ * from what the builder and the schema validator enforce.
13
+ *
14
+ * Uniqueness is checked with the ref lookups rather than `FlatMap.idRefConflict`, and deliberately so: these are
15
+ * a superset of it. FlatMap asks whether another element holds this idRef; the MCP must also refuse a ref that
16
+ * shadows a raw id or a page slug, because its handlers resolve refs through those too — calling both would just
17
+ * run the same rule twice. Null when the ref is usable.
18
+ *
19
+ * Enforced here, at every point a ref BECOMES an idRef — addressing an existing element by its raw id is not
20
+ * charset-checked, which is why the validator cannot simply tighten its own REF_RE for every ref it sees. */
21
+ var guardNewRef = (space, ref, field) => {
22
+ if (!isValidIdRef(ref)) return fail(field, `"${ref}" is not a valid idRef`, ID_REF_HINT);
23
+ if (findElementByRef(space.schema, ref) || findPageByRef(space.schema, ref)) return fail(field, `"${ref}" is already used by another element in this space`, TAKEN_HINT);
24
+ return null;
25
+ };
26
+ var removeFromParent = (space, child) => {
27
+ const parent = child.definition.parentId ? space.schema.flat[child.definition.parentId] : void 0;
28
+ if (parent?.definition.items) parent.definition.items = parent.definition.items.filter((id) => id !== child.id);
10
29
  };
11
30
  var placeChild = (parent, childId, index) => {
12
31
  const items = parent.definition.items ?? (parent.definition.items = []);
13
32
  if (index === void 0 || index < 0 || index >= items.length) items.push(childId);
14
33
  else items.splice(index, 0, childId);
15
34
  };
35
+ var writeInitialState = (el, input, merge) => {
36
+ const current = el.definition.initialState ?? {};
37
+ const next = { ...current };
38
+ if (input.styleVariant !== void 0) if (merge) {
39
+ const merged = { ...current.styleVariant };
40
+ for (const [cls, selectors] of Object.entries(input.styleVariant)) merged[cls] = {
41
+ ...merged[cls],
42
+ ...selectors
43
+ };
44
+ next.styleVariant = merged;
45
+ } else next.styleVariant = input.styleVariant;
46
+ if (input.visibility !== void 0) next.visibility = input.visibility;
47
+ el.definition.initialState = next;
48
+ };
16
49
  var createElement = (space, page, input, parent, index) => {
17
50
  const id = generateObjectId();
18
51
  const { subType, ...props } = {
@@ -21,8 +54,9 @@ var createElement = (space, page, input, parent, index) => {
21
54
  };
22
55
  const styleSelectors = { base: (input.style?.base ?? []).join(" ") };
23
56
  for (const [slot, classes] of Object.entries(input.style?.slots ?? {})) styleSelectors[slot] = classes.join(" ");
24
- space.schema.flat[id] = {
57
+ const el = {
25
58
  id,
59
+ idRef: input.ref,
26
60
  attributes: subType === void 0 ? props : {
27
61
  subType,
28
62
  ...props
@@ -33,12 +67,43 @@ var createElement = (space, page, input, parent, index) => {
33
67
  label: input.label ?? input.ref,
34
68
  type: input.type,
35
69
  items: [],
36
- styleSelectors,
37
- aiRef: input.ref
70
+ styleSelectors
38
71
  }
39
72
  };
73
+ space.schema.flat[id] = el;
40
74
  placeChild(parent, id, index);
41
- for (const child of input.children ?? []) createElement(space, page, child, space.schema.flat[id], void 0);
75
+ indexAddElement(space.schema, el, page.id);
76
+ if (input.initialState) writeInitialState(el, input.initialState, false);
77
+ for (const child of input.children ?? []) createElement(space, page, child, el, void 0);
78
+ };
79
+ /** The idRef an element is wired by, minting one when it has none. Interactions are keyed by idRef, so an element
80
+ * that is about to host or be targeted by a flow must have one — rather than make the agent assign it with a
81
+ * separate patchElement, the MCP gives it a free `<type>-<n>` ref (unique across the space) and proceeds. An
82
+ * element that already has an idRef keeps it. Mutates the element in place and returns the ref. */
83
+ var ensureIdRef = (space, el) => {
84
+ if (el.idRef) return el.idRef;
85
+ const index = spaceIndex(space.schema);
86
+ el.idRef = makeIdRef(el.definition.type, (candidate) => index.elementByRef.has(candidate) || index.pageByRef.has(candidate));
87
+ indexReRefElement(space.schema, el);
88
+ return el.idRef;
89
+ };
90
+ /** The key an interaction node must store to reach a target element. Every ref field also accepts a raw id, so a
91
+ * target given as an id is resolved to the element's idRef — the key the runtime registers callbacks under. A
92
+ * target that has no idRef is given one (see `ensureIdRef`), since it must be reachable to be wired to. A target
93
+ * that resolves to no element is left as written — it is already a ref, or a key only a plugin knows. */
94
+ var resolveTargetRef = (space, elementId) => {
95
+ const el = space.schema.flat[elementId] ?? findElementByRef(space.schema, elementId);
96
+ return el ? ensureIdRef(space, el) : elementId;
97
+ };
98
+ /** Resolve a non-page element within a page for the element-scoped ops (bindings, interactions). Returns the
99
+ * element, or a teachable OpResult when the page or element ref does not resolve — so each op reports the same
100
+ * errors as patchElement without repeating them. */
101
+ var resolveElement = (space, env, pageRef, ref) => {
102
+ const page = findPageByRef(space.schema, pageRef);
103
+ if (!page) return { error: fail("pageRef", `Page "${pageRef}" not found`, `Read plitzi://schema/${env}/pages for valid refs`) };
104
+ const el = resolveRef(space.schema, page, ref);
105
+ if (!el || el.id === page.id) return { error: fail("ref", `Element "${ref}" not found in page "${pageRef}"`, "Use an existing element ref or id") };
106
+ return { el };
42
107
  };
43
108
  //#endregion
44
- export { createElement, folderUri, foldersUri, pageUri, pagesUri, placeChild, removeFromParent, schemaVarsUri };
109
+ export { ID_REF_HINT, collectInputRefs, createElement, ensureIdRef, folderUri, foldersUri, guardNewRef, pageUri, pagesUri, placeChild, removeFromParent, resolveElement, resolveTargetRef, schemaVarsUri, settingsUri, writeInitialState };
@@ -1,7 +1,8 @@
1
- import { empty } from "../../../helpers/opResult.js";
2
- import { MODES, defUri, defsUri, guardKind } from "./write.js";
1
+ import { defUri, defsUri } from "../../../../helpers/uris.js";
2
+ import { empty } from "../../../../helpers/opResult.js";
3
+ import { MODES, guardKind } from "../write.js";
3
4
  import { z } from "zod";
4
- //#region src/modules/mcp/tools/operations/style/deleteDefinition.ts
5
+ //#region src/modules/mcp/tools/operations/style/definitions/deleteDefinition.ts
5
6
  var deleteDefinitionOp = z.object({
6
7
  type: z.literal("deleteDefinition"),
7
8
  ref: z.string().describe("Class ref of the definition to delete")
@@ -1,9 +1,10 @@
1
- import { empty, fail } from "../../../helpers/opResult.js";
2
- import { definitionToAI } from "./translator.js";
3
- import { defUri, defsUri, guardKind, mergePatch, writeStyleItem } from "./write.js";
4
- import { patchCssShape } from "./shared.js";
1
+ import { defUri, defsUri } from "../../../../helpers/uris.js";
2
+ import { empty, fail } from "../../../../helpers/opResult.js";
3
+ import { definitionToAI } from "../translator.js";
4
+ import { guardKind, mergePatch, writeStyleItem } from "../write.js";
5
+ import { patchCssShape } from "../shared.js";
5
6
  import { z } from "zod";
6
- //#region src/modules/mcp/tools/operations/style/patchDefinition.ts
7
+ //#region src/modules/mcp/tools/operations/style/definitions/patchDefinition.ts
7
8
  var patchDefinitionOp = z.object({
8
9
  type: z.literal("patchDefinition"),
9
10
  ref: z.string().describe("Existing class ref to patch"),