@plitzi/sdk-mcp 0.37.9 → 0.37.10

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 (52) hide show
  1. package/CHANGELOG.md +595 -0
  2. package/README.md +2 -2
  3. package/dist/modules/mcp/apps/render/view/streamProgress.ts +1 -3
  4. package/dist/modules/mcp/helpers/agentPrompt.js +7 -5
  5. package/dist/modules/mcp/helpers/guide.js +122 -5
  6. package/dist/modules/mcp/helpers/uris.d.ts +1 -0
  7. package/dist/modules/mcp/helpers/uris.js +2 -1
  8. package/dist/modules/mcp/resources/explain.d.ts +19 -0
  9. package/dist/modules/mcp/resources/explain.js +22 -0
  10. package/dist/modules/mcp/resources/explain.test.d.ts +1 -0
  11. package/dist/modules/mcp/resources/primer.js +6 -1
  12. package/dist/modules/mcp/resources/register.js +10 -0
  13. package/dist/modules/mcp/resources/schema.js +2 -1
  14. package/dist/modules/mcp/server.js +1 -1
  15. package/dist/modules/mcp/tests/flags.test.d.ts +1 -0
  16. package/dist/modules/mcp/tools/apply/dispatch.js +4 -0
  17. package/dist/modules/mcp/tools/apply/index.d.ts +16 -0
  18. package/dist/modules/mcp/tools/apply/index.js +5 -3
  19. package/dist/modules/mcp/tools/operations/index.d.ts +64 -0
  20. package/dist/modules/mcp/tools/operations/index.js +2 -0
  21. package/dist/modules/mcp/tools/operations/schema/elements/patchElement.d.ts +2 -0
  22. package/dist/modules/mcp/tools/operations/schema/elements/patchElement.js +9 -2
  23. package/dist/modules/mcp/tools/operations/schema/elements/upsertElement.js +3 -0
  24. package/dist/modules/mcp/tools/operations/schema/flags/deleteFlag.d.ts +9 -0
  25. package/dist/modules/mcp/tools/operations/schema/flags/deleteFlag.js +21 -0
  26. package/dist/modules/mcp/tools/operations/schema/flags/upsertFlag.d.ts +15 -0
  27. package/dist/modules/mcp/tools/operations/schema/flags/upsertFlag.js +38 -0
  28. package/dist/modules/mcp/tools/operations/schema/index.d.ts +2 -0
  29. package/dist/modules/mcp/tools/operations/schema/operations.d.ts +18 -0
  30. package/dist/modules/mcp/tools/operations/schema/operations.js +4 -0
  31. package/dist/modules/mcp/tools/operations/schema/pages/upsertPage.d.ts +1 -0
  32. package/dist/modules/mcp/tools/operations/schema/pages/upsertPage.js +8 -2
  33. package/dist/modules/mcp/tools/operations/schema/settings/patchSettings.d.ts +1 -0
  34. package/dist/modules/mcp/tools/operations/schema/settings/patchSettings.js +28 -2
  35. package/dist/modules/mcp/tools/operations/schema/shared.d.ts +8 -0
  36. package/dist/modules/mcp/tools/operations/schema/shared.js +10 -2
  37. package/dist/modules/mcp/tools/operations/schema/translator.js +8 -0
  38. package/dist/modules/mcp/tools/operations/schema/write.js +4 -1
  39. package/dist/modules/mcp/tools/operations/schemaIds.js +3 -1
  40. package/dist/modules/mcp/tools/preview.d.ts +16 -0
  41. package/dist/modules/mcp/tools/render.d.ts +16 -0
  42. package/dist/modules/mcp/tools/screenshot.d.ts +16 -0
  43. package/dist/modules/mcp/tools/shared/draftBatch.d.ts +2 -0
  44. package/dist/modules/mcp/tools/shared/draftBatch.js +3 -1
  45. package/dist/modules/mcp/tools/shared/lintDraft.js +16 -4
  46. package/dist/modules/mcp/tools/shared/newSuggestions.d.ts +7 -0
  47. package/dist/modules/mcp/tools/shared/newSuggestions.js +20 -0
  48. package/dist/modules/mcp/tools/validate.d.ts +16 -0
  49. package/dist/modules/mcp/tools/validate.js +8 -6
  50. package/dist/modules/mcp/types/aiSchema.d.ts +6 -1
  51. package/dist/modules/mcp/types/toolTypes.d.ts +4 -0
  52. package/package.json +9 -9
@@ -50,6 +50,8 @@ export declare const documentOperation: z.ZodDiscriminatedUnion<readonly [z.ZodO
50
50
  client: "client";
51
51
  shared: "shared";
52
52
  }>>;
53
+ flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
54
+ anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
53
55
  }, z.core.$strip>, z.ZodObject<{
54
56
  type: z.ZodLiteral<"deleteElement">;
55
57
  pageRef: z.ZodString;
@@ -74,6 +76,7 @@ export declare const documentOperation: z.ZodDiscriminatedUnion<readonly [z.ZodO
74
76
  layout: z.ZodOptional<z.ZodNullable<z.ZodString>>;
75
77
  layoutContainer: z.ZodOptional<z.ZodNullable<z.ZodString>>;
76
78
  enabled: z.ZodOptional<z.ZodBoolean>;
79
+ flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
77
80
  }, z.core.$strip>, z.ZodObject<{
78
81
  type: z.ZodLiteral<"deletePage">;
79
82
  ref: z.ZodString;
@@ -118,6 +121,18 @@ export declare const documentOperation: z.ZodDiscriminatedUnion<readonly [z.ZodO
118
121
  }, z.core.$strip>, z.ZodObject<{
119
122
  type: z.ZodLiteral<"deleteVariable">;
120
123
  name: z.ZodString;
124
+ }, z.core.$strip>, z.ZodObject<{
125
+ type: z.ZodLiteral<"upsertFlag">;
126
+ name: z.ZodString;
127
+ description: z.ZodOptional<z.ZodString>;
128
+ value: z.ZodBoolean;
129
+ rules: z.ZodOptional<z.ZodArray<z.ZodObject<{
130
+ when: z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>;
131
+ value: z.ZodBoolean;
132
+ }, z.core.$strip>>>;
133
+ }, z.core.$strip>, z.ZodObject<{
134
+ type: z.ZodLiteral<"deleteFlag">;
135
+ name: z.ZodString;
121
136
  }, z.core.$strip>, z.ZodObject<{
122
137
  type: z.ZodLiteral<"upsertBinding">;
123
138
  pageRef: z.ZodString;
@@ -221,6 +236,7 @@ export declare const documentOperation: z.ZodDiscriminatedUnion<readonly [z.ZodO
221
236
  }, z.core.$strip>, z.ZodObject<{
222
237
  type: z.ZodLiteral<"patchSettings">;
223
238
  customCss: z.ZodOptional<z.ZodString>;
239
+ notifications: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
224
240
  keepState: z.ZodOptional<z.ZodBoolean>;
225
241
  stateStorage: z.ZodOptional<z.ZodEnum<{
226
242
  localStorage: "localStorage";
@@ -818,6 +834,8 @@ export declare const operation: z.ZodDiscriminatedUnion<[z.ZodObject<{
818
834
  client: "client";
819
835
  shared: "shared";
820
836
  }>>;
837
+ flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
838
+ anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
821
839
  }, z.core.$strip>, z.ZodObject<{
822
840
  type: z.ZodLiteral<"deleteElement">;
823
841
  pageRef: z.ZodString;
@@ -842,6 +860,7 @@ export declare const operation: z.ZodDiscriminatedUnion<[z.ZodObject<{
842
860
  layout: z.ZodOptional<z.ZodNullable<z.ZodString>>;
843
861
  layoutContainer: z.ZodOptional<z.ZodNullable<z.ZodString>>;
844
862
  enabled: z.ZodOptional<z.ZodBoolean>;
863
+ flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
845
864
  }, z.core.$strip>, z.ZodObject<{
846
865
  type: z.ZodLiteral<"deletePage">;
847
866
  ref: z.ZodString;
@@ -886,6 +905,18 @@ export declare const operation: z.ZodDiscriminatedUnion<[z.ZodObject<{
886
905
  }, z.core.$strip>, z.ZodObject<{
887
906
  type: z.ZodLiteral<"deleteVariable">;
888
907
  name: z.ZodString;
908
+ }, z.core.$strip>, z.ZodObject<{
909
+ type: z.ZodLiteral<"upsertFlag">;
910
+ name: z.ZodString;
911
+ description: z.ZodOptional<z.ZodString>;
912
+ value: z.ZodBoolean;
913
+ rules: z.ZodOptional<z.ZodArray<z.ZodObject<{
914
+ when: z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>;
915
+ value: z.ZodBoolean;
916
+ }, z.core.$strip>>>;
917
+ }, z.core.$strip>, z.ZodObject<{
918
+ type: z.ZodLiteral<"deleteFlag">;
919
+ name: z.ZodString;
889
920
  }, z.core.$strip>, z.ZodObject<{
890
921
  type: z.ZodLiteral<"upsertBinding">;
891
922
  pageRef: z.ZodString;
@@ -989,6 +1020,7 @@ export declare const operation: z.ZodDiscriminatedUnion<[z.ZodObject<{
989
1020
  }, z.core.$strip>, z.ZodObject<{
990
1021
  type: z.ZodLiteral<"patchSettings">;
991
1022
  customCss: z.ZodOptional<z.ZodString>;
1023
+ notifications: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
992
1024
  keepState: z.ZodOptional<z.ZodBoolean>;
993
1025
  stateStorage: z.ZodOptional<z.ZodEnum<{
994
1026
  localStorage: "localStorage";
@@ -1858,6 +1890,8 @@ export declare const operations: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject
1858
1890
  client: "client";
1859
1891
  shared: "shared";
1860
1892
  }>>;
1893
+ flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1894
+ anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1861
1895
  }, z.core.$strip>, z.ZodObject<{
1862
1896
  type: z.ZodLiteral<"deleteElement">;
1863
1897
  pageRef: z.ZodString;
@@ -1882,6 +1916,7 @@ export declare const operations: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject
1882
1916
  layout: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1883
1917
  layoutContainer: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1884
1918
  enabled: z.ZodOptional<z.ZodBoolean>;
1919
+ flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
1885
1920
  }, z.core.$strip>, z.ZodObject<{
1886
1921
  type: z.ZodLiteral<"deletePage">;
1887
1922
  ref: z.ZodString;
@@ -1926,6 +1961,18 @@ export declare const operations: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject
1926
1961
  }, z.core.$strip>, z.ZodObject<{
1927
1962
  type: z.ZodLiteral<"deleteVariable">;
1928
1963
  name: z.ZodString;
1964
+ }, z.core.$strip>, z.ZodObject<{
1965
+ type: z.ZodLiteral<"upsertFlag">;
1966
+ name: z.ZodString;
1967
+ description: z.ZodOptional<z.ZodString>;
1968
+ value: z.ZodBoolean;
1969
+ rules: z.ZodOptional<z.ZodArray<z.ZodObject<{
1970
+ when: z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>;
1971
+ value: z.ZodBoolean;
1972
+ }, z.core.$strip>>>;
1973
+ }, z.core.$strip>, z.ZodObject<{
1974
+ type: z.ZodLiteral<"deleteFlag">;
1975
+ name: z.ZodString;
1929
1976
  }, z.core.$strip>, z.ZodObject<{
1930
1977
  type: z.ZodLiteral<"upsertBinding">;
1931
1978
  pageRef: z.ZodString;
@@ -2029,6 +2076,7 @@ export declare const operations: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject
2029
2076
  }, z.core.$strip>, z.ZodObject<{
2030
2077
  type: z.ZodLiteral<"patchSettings">;
2031
2078
  customCss: z.ZodOptional<z.ZodString>;
2079
+ notifications: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
2032
2080
  keepState: z.ZodOptional<z.ZodBoolean>;
2033
2081
  stateStorage: z.ZodOptional<z.ZodEnum<{
2034
2082
  localStorage: "localStorage";
@@ -2893,6 +2941,8 @@ export declare const documentOperations: z.ZodArray<z.ZodDiscriminatedUnion<read
2893
2941
  client: "client";
2894
2942
  shared: "shared";
2895
2943
  }>>;
2944
+ flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2945
+ anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2896
2946
  }, z.core.$strip>, z.ZodObject<{
2897
2947
  type: z.ZodLiteral<"deleteElement">;
2898
2948
  pageRef: z.ZodString;
@@ -2917,6 +2967,7 @@ export declare const documentOperations: z.ZodArray<z.ZodDiscriminatedUnion<read
2917
2967
  layout: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2918
2968
  layoutContainer: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2919
2969
  enabled: z.ZodOptional<z.ZodBoolean>;
2970
+ flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
2920
2971
  }, z.core.$strip>, z.ZodObject<{
2921
2972
  type: z.ZodLiteral<"deletePage">;
2922
2973
  ref: z.ZodString;
@@ -2961,6 +3012,18 @@ export declare const documentOperations: z.ZodArray<z.ZodDiscriminatedUnion<read
2961
3012
  }, z.core.$strip>, z.ZodObject<{
2962
3013
  type: z.ZodLiteral<"deleteVariable">;
2963
3014
  name: z.ZodString;
3015
+ }, z.core.$strip>, z.ZodObject<{
3016
+ type: z.ZodLiteral<"upsertFlag">;
3017
+ name: z.ZodString;
3018
+ description: z.ZodOptional<z.ZodString>;
3019
+ value: z.ZodBoolean;
3020
+ rules: z.ZodOptional<z.ZodArray<z.ZodObject<{
3021
+ when: z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>;
3022
+ value: z.ZodBoolean;
3023
+ }, z.core.$strip>>>;
3024
+ }, z.core.$strip>, z.ZodObject<{
3025
+ type: z.ZodLiteral<"deleteFlag">;
3026
+ name: z.ZodString;
2964
3027
  }, z.core.$strip>, z.ZodObject<{
2965
3028
  type: z.ZodLiteral<"upsertBinding">;
2966
3029
  pageRef: z.ZodString;
@@ -3064,6 +3127,7 @@ export declare const documentOperations: z.ZodArray<z.ZodDiscriminatedUnion<read
3064
3127
  }, z.core.$strip>, z.ZodObject<{
3065
3128
  type: z.ZodLiteral<"patchSettings">;
3066
3129
  customCss: z.ZodOptional<z.ZodString>;
3130
+ notifications: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
3067
3131
  keepState: z.ZodOptional<z.ZodBoolean>;
3068
3132
  stateStorage: z.ZodOptional<z.ZodEnum<{
3069
3133
  localStorage: "localStorage";
@@ -21,6 +21,8 @@ var documentOps = [
21
21
  elementOps.deleteFolder,
22
22
  elementOps.upsertVariable,
23
23
  elementOps.deleteVariable,
24
+ elementOps.upsertFlag,
25
+ elementOps.deleteFlag,
24
26
  elementOps.upsertBinding,
25
27
  elementOps.patchBinding,
26
28
  elementOps.deleteBinding,
@@ -22,6 +22,8 @@ export declare const patchElementOp: z.ZodObject<{
22
22
  client: "client";
23
23
  shared: "shared";
24
24
  }>>;
25
+ flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
26
+ anchor: z.ZodOptional<z.ZodNullable<z.ZodString>>;
25
27
  }, z.core.$strip>;
26
28
  export type PatchElement = z.infer<typeof patchElementOp>;
27
29
  export declare const patchElement: (space: Space, env: Env, op: PatchElement) => OpResult;
@@ -1,8 +1,9 @@
1
1
  import { findRootByRef, invalidateIndex, resolveRef } from "../../../../helpers/space.js";
2
2
  import { pageUri } from "../../../../helpers/uris.js";
3
3
  import { empty, fail } from "../../../../helpers/opResult.js";
4
- import { elementRuntime, initialStateInput, styleRefs } from "../shared.js";
4
+ import { elementAnchor, elementFlag, elementRuntime, initialStateInput, styleRefs } from "../shared.js";
5
5
  import { guardNewRef, writeInitialState } from "../write.js";
6
+ import { flagGateOf } from "@plitzi/sdk-authoring";
6
7
  import { z } from "zod";
7
8
  import { repointIds } from "@plitzi/sdk-schema/helpers/elementId";
8
9
  //#region src/modules/mcp/tools/operations/schema/elements/patchElement.ts
@@ -16,7 +17,9 @@ var patchElementOp = z.object({
16
17
  props: z.record(z.string(), z.unknown()).optional().describe("Merged onto existing props: listed keys change, null unsets a key, others are preserved"),
17
18
  style: styleRefs.optional().describe("Merged onto existing style: base replaces base, listed slots replace slots"),
18
19
  initialState: initialStateInput.optional().describe("Merged onto existing initialState: styleVariant overlays per class/selector, visibility overrides"),
19
- runtime: elementRuntime.optional()
20
+ runtime: elementRuntime.optional(),
21
+ flag: elementFlag.nullable().optional(),
22
+ anchor: elementAnchor.nullable().optional().describe("null removes it")
20
23
  }).describe("Partially update an EXISTING element: only the fields you pass change (props/style/initialState are merged, not replaced). Never creates — fails if ref does not resolve. Use upsertElement to create or fully replace.");
21
24
  var patchElement = (space, env, op) => {
22
25
  const page = findRootByRef(space.schema, op.pageRef);
@@ -48,6 +51,10 @@ var patchElement = (space, env, op) => {
48
51
  }
49
52
  if (op.initialState !== void 0) writeInitialState(el, op.initialState, true);
50
53
  if (op.runtime !== void 0) el.definition.runtime = op.runtime;
54
+ if (op.flag === null) Reflect.deleteProperty(el.definition, "flag");
55
+ else if (op.flag !== void 0) el.definition.flag = flagGateOf(op.flag, `Element "${op.ref}"`);
56
+ if (op.anchor === null) Reflect.deleteProperty(el.definition, "anchor");
57
+ else if (op.anchor !== void 0) el.definition.anchor = op.anchor;
51
58
  return {
52
59
  ...empty(),
53
60
  updated: 1,
@@ -3,6 +3,7 @@ import { pageUri } from "../../../../helpers/uris.js";
3
3
  import { empty, fail } from "../../../../helpers/opResult.js";
4
4
  import { elementInput, position } from "../shared.js";
5
5
  import { DROP_POSITION, collectInputRefs, createElement, guardNewRef, writeInitialState } from "../write.js";
6
+ import { flagGateOf } from "@plitzi/sdk-authoring";
6
7
  import { z } from "zod";
7
8
  //#region src/modules/mcp/tools/operations/schema/elements/upsertElement.ts
8
9
  var upsertElementOp = z.object({
@@ -32,6 +33,8 @@ var upsertElement = (space, env, op) => {
32
33
  }
33
34
  if (op.element.initialState !== void 0) writeInitialState(existing, op.element.initialState, false);
34
35
  if (op.element.runtime !== void 0) existing.definition.runtime = op.element.runtime;
36
+ if (op.element.flag !== void 0) existing.definition.flag = flagGateOf(op.element.flag, `Element "${op.element.ref}"`);
37
+ if (op.element.anchor !== void 0) existing.definition.anchor = op.element.anchor;
35
38
  return {
36
39
  ...empty(),
37
40
  updated: 1,
@@ -0,0 +1,9 @@
1
+ import { z } from 'zod';
2
+ import { Space, OpResult } from '../../../../helpers';
3
+ import { Env } from '../../../../types';
4
+ export declare const deleteFlagOp: z.ZodObject<{
5
+ type: z.ZodLiteral<"deleteFlag">;
6
+ name: z.ZodString;
7
+ }, z.core.$strip>;
8
+ export type DeleteFlag = z.infer<typeof deleteFlagOp>;
9
+ export declare const deleteFlag: (space: Space, env: Env, op: DeleteFlag) => OpResult;
@@ -0,0 +1,21 @@
1
+ import { flagsUri } from "../../../../helpers/uris.js";
2
+ import { empty, fail } from "../../../../helpers/opResult.js";
3
+ import { z } from "zod";
4
+ //#region src/modules/mcp/tools/operations/schema/flags/deleteFlag.ts
5
+ var deleteFlagOp = z.object({
6
+ type: z.literal("deleteFlag"),
7
+ name: z.string()
8
+ }).describe("Remove a feature flag.");
9
+ var deleteFlag = (space, env, op) => {
10
+ const flags = space.schema.flags ?? {};
11
+ if (!Object.hasOwn(flags, op.name)) return fail("name", `The space declares no flag "${op.name}"`, `Read ${flagsUri(env)}`);
12
+ const { [op.name]: _removed, ...rest } = flags;
13
+ space.schema.flags = rest;
14
+ return {
15
+ ...empty(),
16
+ deleted: 1,
17
+ staleResources: [flagsUri(env)]
18
+ };
19
+ };
20
+ //#endregion
21
+ export { deleteFlag, deleteFlagOp };
@@ -0,0 +1,15 @@
1
+ import { z } from 'zod';
2
+ import { Space, OpResult } from '../../../../helpers';
3
+ import { Env } from '../../../../types';
4
+ export declare const upsertFlagOp: z.ZodObject<{
5
+ type: z.ZodLiteral<"upsertFlag">;
6
+ name: z.ZodString;
7
+ description: z.ZodOptional<z.ZodString>;
8
+ value: z.ZodBoolean;
9
+ rules: z.ZodOptional<z.ZodArray<z.ZodObject<{
10
+ when: z.ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, z.core.$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>;
11
+ value: z.ZodBoolean;
12
+ }, z.core.$strip>>>;
13
+ }, z.core.$strip>;
14
+ export type UpsertFlag = z.infer<typeof upsertFlagOp>;
15
+ export declare const upsertFlag: (space: Space, env: Env, op: UpsertFlag) => OpResult;
@@ -0,0 +1,38 @@
1
+ import { flagsUri } from "../../../../helpers/uris.js";
2
+ import { empty, fail } from "../../../../helpers/opResult.js";
3
+ import { ruleGroup } from "../shared.js";
4
+ import { z } from "zod";
5
+ import { isFlagName, isSchemaFlag } from "@plitzi/sdk-shared/flags";
6
+ //#region src/modules/mcp/tools/operations/schema/flags/upsertFlag.ts
7
+ var ruleInput = z.object({
8
+ when: ruleGroup,
9
+ value: z.boolean()
10
+ });
11
+ var upsertFlagOp = z.object({
12
+ type: z.literal("upsertFlag"),
13
+ name: z.string(),
14
+ description: z.string().optional(),
15
+ value: z.boolean().describe("When no rule matches"),
16
+ rules: z.array(ruleInput).optional()
17
+ }).describe("Declare or replace a feature flag (guide: Feature flags).");
18
+ var upsertFlag = (space, env, op) => {
19
+ if (!isFlagName(op.name)) return fail("name", `"${op.name}" is not a flag name`, "Letters, digits and \"_\", starting with a letter or \"_\"");
20
+ const flag = {
21
+ ...op.description ? { description: op.description } : {},
22
+ value: op.value,
23
+ rules: op.rules ?? []
24
+ };
25
+ if (!isSchemaFlag(flag)) return fail("rules", "A rule is { when: { combinator, rules: [...] }, value: true | false }", "Fix the rule groups");
26
+ const existed = Object.hasOwn(space.schema.flags ?? {}, op.name);
27
+ space.schema.flags = {
28
+ ...space.schema.flags,
29
+ [op.name]: flag
30
+ };
31
+ return {
32
+ ...empty(),
33
+ ...existed ? { updated: 1 } : { created: 1 },
34
+ staleResources: [flagsUri(env)]
35
+ };
36
+ };
37
+ //#endregion
38
+ export { upsertFlag, upsertFlagOp };
@@ -14,6 +14,8 @@ export * from './folders/upsertFolder';
14
14
  export * from './folders/deleteFolder';
15
15
  export * from './variables/upsertVariable';
16
16
  export * from './variables/deleteVariable';
17
+ export * from './flags/upsertFlag';
18
+ export * from './flags/deleteFlag';
17
19
  export * from './bindings/upsertBinding';
18
20
  export * from './bindings/patchBinding';
19
21
  export * from './bindings/deleteBinding';
@@ -50,6 +50,8 @@ export declare const elementOps: {
50
50
  client: "client";
51
51
  shared: "shared";
52
52
  }>>;
53
+ flag: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
54
+ anchor: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
53
55
  }, import('zod/v4/core').$strip>;
54
56
  deleteElement: import('zod').ZodObject<{
55
57
  type: import('zod').ZodLiteral<"deleteElement">;
@@ -77,6 +79,7 @@ export declare const elementOps: {
77
79
  layout: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
78
80
  layoutContainer: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
79
81
  enabled: import('zod').ZodOptional<import('zod').ZodBoolean>;
82
+ flag: import('zod').ZodOptional<import('zod').ZodNullable<import('zod').ZodString>>;
80
83
  }, import('zod/v4/core').$strip>;
81
84
  deletePage: import('zod').ZodObject<{
82
85
  type: import('zod').ZodLiteral<"deletePage">;
@@ -129,6 +132,20 @@ export declare const elementOps: {
129
132
  type: import('zod').ZodLiteral<"deleteVariable">;
130
133
  name: import('zod').ZodString;
131
134
  }, import('zod/v4/core').$strip>;
135
+ upsertFlag: import('zod').ZodObject<{
136
+ type: import('zod').ZodLiteral<"upsertFlag">;
137
+ name: import('zod').ZodString;
138
+ description: import('zod').ZodOptional<import('zod').ZodString>;
139
+ value: import('zod').ZodBoolean;
140
+ rules: import('zod').ZodOptional<import('zod').ZodArray<import('zod').ZodObject<{
141
+ when: import('zod').ZodType<import('@plitzi/sdk-shared').RuleGroup, unknown, import('zod/v4/core').$ZodTypeInternals<import('@plitzi/sdk-shared').RuleGroup, unknown>>;
142
+ value: import('zod').ZodBoolean;
143
+ }, import('zod/v4/core').$strip>>>;
144
+ }, import('zod/v4/core').$strip>;
145
+ deleteFlag: import('zod').ZodObject<{
146
+ type: import('zod').ZodLiteral<"deleteFlag">;
147
+ name: import('zod').ZodString;
148
+ }, import('zod/v4/core').$strip>;
132
149
  upsertBinding: import('zod').ZodObject<{
133
150
  type: import('zod').ZodLiteral<"upsertBinding">;
134
151
  pageRef: import('zod').ZodString;
@@ -238,6 +255,7 @@ export declare const elementOps: {
238
255
  patchSettings: import('zod').ZodObject<{
239
256
  type: import('zod').ZodLiteral<"patchSettings">;
240
257
  customCss: import('zod').ZodOptional<import('zod').ZodString>;
258
+ notifications: import('zod').ZodOptional<import('zod').ZodRecord<import('zod').ZodString, import('zod').ZodNullable<import('zod').ZodString>>>;
241
259
  keepState: import('zod').ZodOptional<import('zod').ZodBoolean>;
242
260
  stateStorage: import('zod').ZodOptional<import('zod').ZodEnum<{
243
261
  localStorage: "localStorage";
@@ -8,6 +8,8 @@ import { moveElementOp } from "./elements/moveElement.js";
8
8
  import { patchElementOp } from "./elements/patchElement.js";
9
9
  import { repeatElementOp } from "./elements/repeatElement.js";
10
10
  import { upsertElementOp } from "./elements/upsertElement.js";
11
+ import { deleteFlagOp } from "./flags/deleteFlag.js";
12
+ import { upsertFlagOp } from "./flags/upsertFlag.js";
11
13
  import { deleteFolderOp } from "./folders/deleteFolder.js";
12
14
  import { upsertFolderOp } from "./folders/upsertFolder.js";
13
15
  import { deleteInteractionOp } from "./interactions/deleteInteraction.js";
@@ -35,6 +37,8 @@ var elementOps = {
35
37
  deleteFolder: deleteFolderOp,
36
38
  upsertVariable: upsertVariableOp,
37
39
  deleteVariable: deleteVariableOp,
40
+ upsertFlag: upsertFlagOp,
41
+ deleteFlag: deleteFlagOp,
38
42
  upsertBinding: upsertBindingOp,
39
43
  patchBinding: patchBindingOp,
40
44
  deleteBinding: deleteBindingOp,
@@ -11,6 +11,7 @@ export declare const upsertPageOp: z.ZodObject<{
11
11
  layout: z.ZodOptional<z.ZodNullable<z.ZodString>>;
12
12
  layoutContainer: z.ZodOptional<z.ZodNullable<z.ZodString>>;
13
13
  enabled: z.ZodOptional<z.ZodBoolean>;
14
+ flag: z.ZodOptional<z.ZodNullable<z.ZodString>>;
14
15
  }, z.core.$strip>;
15
16
  export type UpsertPage = z.infer<typeof upsertPageOp>;
16
17
  export declare const upsertPage: (space: Space, env: Env, op: UpsertPage) => OpResult;
@@ -1,7 +1,9 @@
1
1
  import { findFolderByRef, findLayoutByRef, findPageByRef, indexAddPage, resolveRef } from "../../../../helpers/space.js";
2
2
  import { layoutsUri, pageUri, pagesUri } from "../../../../helpers/uris.js";
3
3
  import { empty, fail } from "../../../../helpers/opResult.js";
4
+ import { elementFlag } from "../shared.js";
4
5
  import { guardNewRef } from "../write.js";
6
+ import { flagGateOf } from "@plitzi/sdk-authoring";
5
7
  import { z } from "zod";
6
8
  //#region src/modules/mcp/tools/operations/schema/pages/upsertPage.ts
7
9
  var upsertPageOp = z.object({
@@ -13,7 +15,8 @@ var upsertPageOp = z.object({
13
15
  default: z.boolean().optional(),
14
16
  layout: z.string().nullable().optional().describe("Ref of the layout shell this page renders inside; \"\" or null detaches it. See plitzi://schema/{env}/layouts."),
15
17
  layoutContainer: z.string().nullable().optional().describe("Ref of the container INSIDE that shell where this page body goes — the slot. Must belong to it."),
16
- 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")
18
+ 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"),
19
+ flag: elementFlag.nullable().optional()
17
20
  }).describe("Create a page, or update it when ref already exists (only the fields you pass change).");
18
21
  var upsertPage = (space, env, op) => {
19
22
  const slug = op.slug === void 0 ? void 0 : op.slug.replace(/^\/+/, "");
@@ -63,6 +66,8 @@ var upsertPage = (space, env, op) => {
63
66
  ...layoutValue !== void 0 ? { layout: layoutValue } : {},
64
67
  ...slotValue !== void 0 ? { layoutContainer: slotValue } : {}
65
68
  };
69
+ if (op.flag === null) Reflect.deleteProperty(existing.definition, "flag");
70
+ else if (op.flag !== void 0) existing.definition.flag = flagGateOf(op.flag, `Page "${op.ref}"`);
66
71
  return {
67
72
  ...empty(),
68
73
  updated: 1,
@@ -92,7 +97,8 @@ var upsertPage = (space, env, op) => {
92
97
  label: op.label ?? op.ref,
93
98
  type: "page",
94
99
  items: [],
95
- styleSelectors: { base: "" }
100
+ styleSelectors: { base: "" },
101
+ ...op.flag ? { flag: flagGateOf(op.flag, `Page "${op.ref}"`) } : {}
96
102
  }
97
103
  };
98
104
  space.schema.flat[id] = page;
@@ -4,6 +4,7 @@ import { Env } from '../../../../types';
4
4
  export declare const patchSettingsOp: z.ZodObject<{
5
5
  type: z.ZodLiteral<"patchSettings">;
6
6
  customCss: z.ZodOptional<z.ZodString>;
7
+ notifications: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodNullable<z.ZodString>>>;
7
8
  keepState: z.ZodOptional<z.ZodBoolean>;
8
9
  stateStorage: z.ZodOptional<z.ZodEnum<{
9
10
  localStorage: "localStorage";
@@ -1,5 +1,6 @@
1
1
  import { settingsUri } from "../../../../helpers/uris.js";
2
2
  import { empty, fail } from "../../../../helpers/opResult.js";
3
+ import { NOTIFICATIONS_FIELDS, splitNotificationsCss, withNotificationsCss } from "@plitzi/sdk-authoring";
3
4
  import { z } from "zod";
4
5
  import { channelProblems } from "@plitzi/sdk-shared/realtime";
5
6
  //#region src/modules/mcp/tools/operations/schema/settings/patchSettings.ts
@@ -21,9 +22,11 @@ var channel = z.object({
21
22
  publish: z.enum(["clients", "server"]).optional(),
22
23
  presence: z.boolean().optional()
23
24
  });
25
+ var notifications = z.record(z.string(), z.string().nullable());
24
26
  var patchSettingsOp = z.object({
25
27
  type: z.literal("patchSettings"),
26
28
  customCss: z.string().optional().describe("Raw global CSS for the whole space (keyframes, @font-face, resets)"),
29
+ notifications: notifications.optional().describe(`The toasts' look: ${NOTIFICATIONS_FIELDS.join(", ")} — CSS values; null removes one`),
27
30
  keepState: z.boolean().optional().describe("Keep runtime state (setState keys) across reloads"),
28
31
  stateStorage: z.enum(["localStorage", "sessionStorage"]).optional(),
29
32
  transientState: z.array(z.string()).optional().describe("Top-level state keys never kept"),
@@ -44,7 +47,7 @@ var patchSettingsOp = z.object({
44
47
  sessionGate: z.enum(["optimistic", "strict"]).optional().describe("Render from the stored session and confirm behind it (default), or wait for the confirmation"),
45
48
  sessionRevalidateSeconds: z.number().optional(),
46
49
  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).");
50
+ }).describe("Merge space-level settings — global CSS, notifications, 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
51
  /** The space's channels with the patch merged in, pattern by pattern — `null` takes one out. */
49
52
  var mergeChannels = (current, patch) => {
50
53
  const merged = {
@@ -53,8 +56,23 @@ var mergeChannels = (current, patch) => {
53
56
  };
54
57
  return Object.fromEntries(Object.entries(merged).filter((entry) => entry[1] !== null));
55
58
  };
59
+ /**
60
+ * The space's `customCss` with the patch's own CSS and notifications in it. Both live in that one string — the
61
+ * notifications as the rule authoring writes for them — so each is read out of it, changed apart, and written back
62
+ * together: a new `customCss` keeps the notifications, and new notifications keep the space's CSS.
63
+ */
64
+ var patchCustomCss = (current, customCss, patch) => {
65
+ const was = splitNotificationsCss(current);
66
+ const sent = customCss === void 0 ? void 0 : splitNotificationsCss(customCss);
67
+ const merged = {
68
+ ...was.notifications,
69
+ ...sent?.notifications,
70
+ ...patch
71
+ };
72
+ return withNotificationsCss(sent?.customCss ?? was.customCss, Object.fromEntries(Object.entries(merged).filter((entry) => typeof entry[1] === "string")));
73
+ };
56
74
  var patchSettings = (space, env, op) => {
57
- const { type, channels, ...patch } = op;
75
+ const { type, channels, customCss, notifications: notificationsPatch, ...patch } = op;
58
76
  for (const [pattern, declaration] of Object.entries(channels ?? {})) {
59
77
  const [problem] = declaration === null ? [] : channelProblems(pattern, declaration);
60
78
  if (problem) return fail(`channels["${pattern}"]`, `Channel "${pattern}": ${problem}.`, "Fix the pattern or declaration and send it again");
@@ -62,6 +80,14 @@ var patchSettings = (space, env, op) => {
62
80
  const next = { ...space.schema.settings };
63
81
  for (const [key, value] of Object.entries(patch)) next[key] = value;
64
82
  if (channels) next.channels = mergeChannels(space.schema.settings.channels, channels);
83
+ if (customCss !== void 0 || notificationsPatch) {
84
+ const current = space.schema.settings.customCss;
85
+ try {
86
+ next.customCss = patchCustomCss(typeof current === "string" ? current : "", customCss, notificationsPatch);
87
+ } catch (error) {
88
+ return fail("notifications", error instanceof Error ? error.message : String(error), "Write one CSS value per field — a colour, a length or a token like var(--card)");
89
+ }
90
+ }
65
91
  space.schema.settings = next;
66
92
  return {
67
93
  ...empty(),
@@ -18,6 +18,8 @@ export interface ElementInput {
18
18
  };
19
19
  initialState?: InitialStateInput;
20
20
  runtime?: ElementRuntime;
21
+ flag?: string;
22
+ anchor?: string;
21
23
  children?: ElementInput[];
22
24
  }
23
25
  export declare const styleRefs: z.ZodObject<{
@@ -33,6 +35,10 @@ export declare const elementRuntime: z.ZodEnum<{
33
35
  client: "client";
34
36
  shared: "shared";
35
37
  }>;
38
+ /** The feature flag an element exists under — `'name'` while on, `'!name'` while off. Not a visibility. */
39
+ export declare const elementFlag: z.ZodString;
40
+ /** The element's `id` in the DOM, so `/page#anchor` lands on it — the one pattern every writer holds it to. */
41
+ export declare const elementAnchor: z.ZodString;
36
42
  export declare const initialStateInput: z.ZodObject<{
37
43
  styleVariant: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>>>;
38
44
  visibility: z.ZodOptional<z.ZodBoolean>;
@@ -56,6 +62,8 @@ export declare const elementShape: {
56
62
  client: "client";
57
63
  shared: "shared";
58
64
  }>>;
65
+ flag: z.ZodOptional<z.ZodString>;
66
+ anchor: z.ZodOptional<z.ZodString>;
59
67
  };
60
68
  export declare const elementInput: z.ZodType<ElementInput>;
61
69
  export declare const position: z.ZodEnum<{
@@ -1,4 +1,6 @@
1
1
  import { z } from "zod";
2
+ import { FLAG_GATE_PATTERN } from "@plitzi/sdk-shared/flags";
3
+ import { ANCHOR_PATTERN } from "@plitzi/sdk-shared/schema/anchor";
2
4
  //#region src/modules/mcp/tools/operations/schema/shared.ts
3
5
  var combinator = z.enum(["and", "or"]);
4
6
  var operator = z.enum([
@@ -64,6 +66,10 @@ var elementRuntime = z.enum([
64
66
  "client",
65
67
  "shared"
66
68
  ]).describe("Where this element renders: \"shared\" (default, both), \"client\" (browser only), or \"server\" (SSR only). An apiContainer MUST be \"server\" to read through a connector — a client one calls its own `query` URL instead.");
69
+ /** The feature flag an element exists under — `'name'` while on, `'!name'` while off. Not a visibility. */
70
+ var elementFlag = z.string().regex(FLAG_GATE_PATTERN).describe("Feature flag: `name` renders only while on, `!name` only while off");
71
+ /** The element's `id` in the DOM, so `/page#anchor` lands on it — the one pattern every writer holds it to. */
72
+ var elementAnchor = z.string().regex(ANCHOR_PATTERN).describe("Its DOM id, for `/page#anchor` and the `hash` of a link; one per page");
67
73
  var initialStateInput = z.object({
68
74
  styleVariant: styleVariantInput.optional().describe("Variant each attached class uses: { className: { base|slot: variantName | [names] } }"),
69
75
  visibility: z.boolean().optional().describe("Initial visibility of the element")
@@ -76,7 +82,9 @@ var elementShape = {
76
82
  props: z.record(z.string(), z.unknown()).optional().describe("Full replacement on update"),
77
83
  style: styleRefs.optional().describe("Definition refs per slot; style the element by attaching a definition"),
78
84
  initialState: initialStateInput.optional().describe("Applied style variant(s) and initial visibility (see plitzi://guide styling)"),
79
- runtime: elementRuntime.optional()
85
+ runtime: elementRuntime.optional(),
86
+ flag: elementFlag.optional(),
87
+ anchor: elementAnchor.optional()
80
88
  };
81
89
  var elementInput = z.lazy(() => z.object({
82
90
  ...elementShape,
@@ -133,4 +141,4 @@ var interactionNode = z.object({
133
141
  preview: z.record(z.string(), z.unknown()).optional()
134
142
  });
135
143
  //#endregion
136
- export { bindingCategory, bindingInput, elementInput, elementRuntime, elementShape, initialStateInput, interactionNode, interactionNodeType, position, ruleGroup, scalar, styleRefs, styleVariantInput };
144
+ export { bindingCategory, bindingInput, elementAnchor, elementFlag, elementInput, elementRuntime, elementShape, initialStateInput, interactionNode, interactionNodeType, position, ruleGroup, scalar, styleRefs, styleVariantInput };
@@ -2,6 +2,7 @@ import { computeVersion } from "../../../helpers/computeVersion.js";
2
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 { flagSpecOf, splitNotificationsCss } from "@plitzi/sdk-authoring";
5
6
  import { descendants } from "@plitzi/sdk-schema/helpers/elementTree";
6
7
  //#region src/modules/mcp/tools/operations/schema/translator.ts
7
8
  var splitClasses = (value) => value ? value.split(/\s+/).filter(Boolean) : [];
@@ -182,6 +183,7 @@ var elementDetailToAI = (schema, el, style) => {
182
183
  childRefs: children.length > 0 ? children.map((child) => child.id) : void 0
183
184
  };
184
185
  if (el.definition.runtime) detail.runtime = el.definition.runtime;
186
+ if (el.definition.flag) detail.flag = flagSpecOf(el.definition.flag);
185
187
  const initialState = initialStateToAI(el);
186
188
  if (initialState) detail.initialState = initialState;
187
189
  const bindings = bindingsToAI(el.definition.bindings);
@@ -223,6 +225,12 @@ var schemaVariablesToAI = (schema, includeSubValues = true) => {
223
225
  var settingsToAI = (schema) => {
224
226
  const result = {};
225
227
  for (const [key, value] of Object.entries(schema.settings)) result[key] = value;
228
+ if (typeof schema.settings.customCss === "string") {
229
+ const { notifications, customCss } = splitNotificationsCss(schema.settings.customCss);
230
+ if (customCss) result.customCss = customCss;
231
+ else delete result.customCss;
232
+ if (Object.keys(notifications).length > 0) result.notifications = notifications;
233
+ }
226
234
  return result;
227
235
  };
228
236
  //#endregion
@@ -1,6 +1,7 @@
1
1
  import { findRootByRef, indexAddElement, resolveRef } from "../../../helpers/space.js";
2
2
  import { folderUri, foldersUri, layoutsUri, pageUri, pagesUri, schemaVarsUri, settingsUri } from "../../../helpers/uris.js";
3
3
  import { fail } from "../../../helpers/opResult.js";
4
+ import { flagGateOf } from "@plitzi/sdk-authoring";
4
5
  import { documentIds } from "@plitzi/sdk-schema/helpers/components";
5
6
  import { elementIdConflict, isValidElementId } from "@plitzi/sdk-schema/helpers/elementId";
6
7
  import FlatMap from "@plitzi/sdk-schema/helpers/FlatMap";
@@ -64,7 +65,9 @@ var createElement = (space, page, input, anchorId, drop) => {
64
65
  type: input.type,
65
66
  items: [],
66
67
  styleSelectors,
67
- ...input.runtime === void 0 ? {} : { runtime: input.runtime }
68
+ ...input.runtime === void 0 ? {} : { runtime: input.runtime },
69
+ ...input.flag === void 0 ? {} : { flag: flagGateOf(input.flag, `Element "${input.ref}"`) },
70
+ ...input.anchor === void 0 ? {} : { anchor: input.anchor }
68
71
  }
69
72
  };
70
73
  if (!new FlatMap({ flat: space.schema.flat }).addElement(el, anchorId, drop)) return false;