@blokkli/editor 2.0.0-alpha.45 → 2.0.0-alpha.47

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 (87) hide show
  1. package/dist/module.d.mts +2 -2
  2. package/dist/module.json +1 -1
  3. package/dist/module.mjs +23 -1
  4. package/dist/modules/agent/index.d.mts +1 -1
  5. package/dist/modules/agent/runtime/app/helpers/validation.d.ts +13 -0
  6. package/dist/modules/agent/runtime/app/helpers/validation.js +22 -0
  7. package/dist/modules/agent/runtime/app/tools/add_content_search_paragraph/index.js +12 -0
  8. package/dist/modules/agent/runtime/app/tools/add_fragment/index.js +12 -1
  9. package/dist/modules/agent/runtime/app/tools/add_media_paragraph/index.js +12 -0
  10. package/dist/modules/agent/runtime/app/tools/add_paragraphs/index.js +10 -0
  11. package/dist/modules/agent/runtime/app/tools/add_reusable_paragraph/index.js +12 -0
  12. package/dist/modules/agent/runtime/app/tools/add_template/index.js +5 -0
  13. package/dist/modules/agent/runtime/app/tools/delegate_text_rewrite/index.js +15 -0
  14. package/dist/modules/agent/runtime/app/tools/delete_paragraphs/index.js +12 -0
  15. package/dist/modules/agent/runtime/app/tools/detach_reusable_paragraph/index.js +12 -0
  16. package/dist/modules/agent/runtime/app/tools/duplicate_paragraphs/index.js +16 -1
  17. package/dist/modules/agent/runtime/app/tools/move_paragraphs/index.js +17 -0
  18. package/dist/modules/agent/runtime/app/tools/rearrange_paragraphs/index.js +11 -0
  19. package/dist/modules/agent/runtime/app/tools/replace_content_search_item/index.js +8 -0
  20. package/dist/modules/agent/runtime/app/tools/replace_media_field/index.js +10 -0
  21. package/dist/modules/agent/runtime/app/tools/set_paragraph_options/index.js +10 -0
  22. package/dist/modules/agent/runtime/app/tools/swap_paragraphs/index.js +15 -0
  23. package/dist/modules/agent/runtime/app/tools/update_text_fields/index.js +21 -1
  24. package/dist/modules/agent/runtime/app/types/index.d.ts +6 -6
  25. package/dist/modules/charts/index.d.mts +1 -1
  26. package/dist/modules/drupal/index.d.mts +1 -1
  27. package/dist/modules/drupal/index.mjs +2 -1
  28. package/dist/modules/drupal/runtime/adapter/index.js +15 -3
  29. package/dist/modules/table-of-contents/index.d.mts +1 -1
  30. package/dist/runtime/editor/components/Actions/index.vue +47 -2
  31. package/dist/runtime/editor/components/AnimationCanvas/index.vue +6 -3
  32. package/dist/runtime/editor/components/BundleSelector/index.d.vue.ts +8 -4
  33. package/dist/runtime/editor/components/BundleSelector/index.vue +111 -13
  34. package/dist/runtime/editor/components/BundleSelector/index.vue.d.ts +8 -4
  35. package/dist/runtime/editor/components/EditProvider.vue +2 -2
  36. package/dist/runtime/editor/components/FlexTextarea/index.vue +227 -11
  37. package/dist/runtime/editor/css/output.css +1 -1
  38. package/dist/runtime/editor/features/add-list/Blocks/index.vue +6 -3
  39. package/dist/runtime/editor/features/analyze/Renderer/index.vue +1 -1
  40. package/dist/runtime/editor/features/block-scheduler/index.vue +7 -1
  41. package/dist/runtime/editor/features/changelog/Dialog/index.d.vue.ts +7 -0
  42. package/dist/runtime/editor/features/changelog/Dialog/index.vue +43 -0
  43. package/dist/runtime/editor/features/changelog/Dialog/index.vue.d.ts +7 -0
  44. package/dist/runtime/editor/features/changelog/changelog.json +50 -0
  45. package/dist/runtime/editor/features/changelog/index.d.vue.ts +3 -0
  46. package/dist/runtime/editor/features/changelog/index.vue +56 -0
  47. package/dist/runtime/editor/features/changelog/index.vue.d.ts +3 -0
  48. package/dist/runtime/editor/features/clipboard/index.vue +6 -1
  49. package/dist/runtime/editor/features/comments/AddForm/index.d.vue.ts +2 -2
  50. package/dist/runtime/editor/features/comments/AddForm/index.vue.d.ts +2 -2
  51. package/dist/runtime/editor/features/delete/index.vue +17 -2
  52. package/dist/runtime/editor/features/dragging-overlay/Renderer/index.vue +12 -2
  53. package/dist/runtime/editor/features/dragging-overlay/index.vue +5 -2
  54. package/dist/runtime/editor/features/duplicate/index.vue +23 -7
  55. package/dist/runtime/editor/features/edit/index.vue +29 -8
  56. package/dist/runtime/editor/features/editable-field/Overlay/Plaintext/index.vue +0 -1
  57. package/dist/runtime/editor/features/editable-field/index.vue +15 -1
  58. package/dist/runtime/editor/features/fragments/index.vue +5 -2
  59. package/dist/runtime/editor/features/hover/Renderer/index.vue +19 -6
  60. package/dist/runtime/editor/features/hover/Renderer/vertex.glsl +5 -2
  61. package/dist/runtime/editor/features/library/index.vue +52 -8
  62. package/dist/runtime/editor/features/media-library/index.vue +7 -2
  63. package/dist/runtime/editor/features/multi-select/Renderer/index.vue +4 -1
  64. package/dist/runtime/editor/features/search/index.vue +7 -2
  65. package/dist/runtime/editor/features/selection/AddButtons/Renderer/index.vue +1 -1
  66. package/dist/runtime/editor/features/selection/AddButtons/index.vue +26 -2
  67. package/dist/runtime/editor/features/selection/Renderer/index.vue +23 -5
  68. package/dist/runtime/editor/features/selection/Renderer/vertex.glsl +5 -2
  69. package/dist/runtime/editor/features/selection/index.vue +17 -5
  70. package/dist/runtime/editor/features/translations/index.vue +17 -11
  71. package/dist/runtime/editor/helpers/dropTargets/index.d.ts +1 -1
  72. package/dist/runtime/editor/helpers/dropTargets/index.js +2 -2
  73. package/dist/runtime/editor/plugins/ItemAction/index.d.vue.ts +4 -1
  74. package/dist/runtime/editor/plugins/ItemAction/index.vue +9 -3
  75. package/dist/runtime/editor/plugins/ItemAction/index.vue.d.ts +4 -1
  76. package/dist/runtime/editor/providers/permissions.d.ts +22 -1
  77. package/dist/runtime/editor/providers/permissions.js +99 -3
  78. package/dist/runtime/editor/providers/selection.d.ts +2 -1
  79. package/dist/runtime/editor/providers/selection.js +10 -5
  80. package/dist/runtime/editor/translations/de.json +109 -1
  81. package/dist/runtime/editor/translations/fr.json +109 -1
  82. package/dist/runtime/editor/translations/gsw_CH.json +109 -1
  83. package/dist/runtime/editor/translations/it.json +109 -1
  84. package/dist/runtime/editor/types/definitions.d.ts +2 -0
  85. package/dist/shared/{editor.BdBm1Z7C.d.mts → editor.BVregnEC.d.mts} +24 -0
  86. package/dist/types.d.mts +1 -1
  87. package/package.json +2 -1
package/dist/module.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { NuxtModule } from 'nuxt/schema';
2
- import { M as ModuleOptions } from './shared/editor.BdBm1Z7C.mjs';
3
- export { a as ModuleHooks } from './shared/editor.BdBm1Z7C.mjs';
2
+ import { M as ModuleOptions } from './shared/editor.BVregnEC.mjs';
3
+ export { a as ModuleHooks } from './shared/editor.BVregnEC.mjs';
4
4
  import 'consola';
5
5
  import '../dist/global/types/definitions.js';
6
6
  import '../dist/global/types/theme.js';
package/dist/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@blokkli/editor",
3
3
  "configKey": "blokkli",
4
- "version": "2.0.0-alpha.45",
4
+ "version": "2.0.0-alpha.47",
5
5
  "compatibility": {
6
6
  "nuxt": ">=3.15.0"
7
7
  },
package/dist/module.mjs CHANGED
@@ -18,7 +18,7 @@ import 'typescript';
18
18
  import 'oxc-walker';
19
19
 
20
20
  const name = "@blokkli/editor";
21
- const version = "2.0.0-alpha.45";
21
+ const version = "2.0.0-alpha.47";
22
22
 
23
23
  function validateOption(optionKey, option, icons) {
24
24
  const errors = [];
@@ -1426,6 +1426,7 @@ const USED_MATERIAL_ICONS = [
1426
1426
  "bk_mdi_build-fill",
1427
1427
  "bk_mdi_calendar_clock",
1428
1428
  "bk_mdi_calendar_month",
1429
+ "bk_mdi_campaign",
1429
1430
  "bk_mdi_chat",
1430
1431
  "bk_mdi_check",
1431
1432
  "bk_mdi_check_box",
@@ -1467,6 +1468,7 @@ const USED_MATERIAL_ICONS = [
1467
1468
  "bk_mdi_keyboard_arrow_down",
1468
1469
  "bk_mdi_keyboard_command_key",
1469
1470
  "bk_mdi_lists",
1471
+ "bk_mdi_lock",
1470
1472
  "bk_mdi_logo_dev",
1471
1473
  "bk_mdi_menu",
1472
1474
  "bk_mdi_mobile",
@@ -2662,6 +2664,17 @@ export const forceDefaultLanguage = ${JSON.stringify(
2662
2664
  )}
2663
2665
 
2664
2666
  export const featureFragmentNames = ${JSON.stringify(featureFragmentNames)}
2667
+
2668
+ export const textAutoReplace = ${(() => {
2669
+ const opt = ctx.helper.options.textAutoReplace;
2670
+ const all = opt === void 0 || opt === true;
2671
+ const obj = typeof opt === "object" && opt !== null ? opt : null;
2672
+ return JSON.stringify({
2673
+ quotes: obj ? obj.quotes ?? true : all,
2674
+ ellipsis: obj ? obj.ellipsis ?? true : all,
2675
+ enDash: obj ? obj.enDash ?? true : all
2676
+ });
2677
+ })()}
2665
2678
  `;
2666
2679
  },
2667
2680
  (ctx) => {
@@ -2719,6 +2732,15 @@ export declare const forceDefaultLanguage: boolean
2719
2732
  * The fragment names provided by features.
2720
2733
  */
2721
2734
  export declare const featureFragmentNames: string[]
2735
+
2736
+ /**
2737
+ * Text auto-replace configuration.
2738
+ */
2739
+ export declare const textAutoReplace: {
2740
+ quotes: boolean
2741
+ ellipsis: boolean
2742
+ enDash: boolean
2743
+ }
2722
2744
  `;
2723
2745
  }
2724
2746
  );
@@ -1,4 +1,4 @@
1
- import { B as BlokkliModule } from '../../shared/editor.BdBm1Z7C.mjs';
1
+ import { B as BlokkliModule } from '../../shared/editor.BVregnEC.mjs';
2
2
  import 'nuxt/schema';
3
3
  import 'consola';
4
4
  import '../../../dist/global/types/definitions.js';
@@ -1,5 +1,7 @@
1
1
  import type { BlokkliApp } from '#blokkli/editor/types/app';
2
2
  import type { RenderedFieldListItem } from '#blokkli/editor/types/field';
3
+ import type { BlockPermission } from '#blokkli/editor/types/definitions';
4
+ import type { ToolError } from '../types/index.js';
3
5
  type ValidationResult = {
4
6
  valid: true;
5
7
  } | {
@@ -32,4 +34,15 @@ export declare function validateFieldCardinality(app: BlokkliApp, host: Rendered
32
34
  * Validate that all bundles are allowed in the field.
33
35
  */
34
36
  export declare function validateBundlesAllowed(app: BlokkliApp, host: RenderedFieldListItem['host'], bundles: string[]): ValidationResult;
37
+ /**
38
+ * Check that none of the given blocks are inside a restricted ancestor.
39
+ * Returns a ToolError if any block has a restricted ancestor, or undefined if
40
+ * all are unrestricted.
41
+ */
42
+ export declare function requireNoRestrictedAncestor(app: BlokkliApp, uuids: string[]): ToolError | undefined;
43
+ /**
44
+ * Check that the user has a specific permission for all given bundles.
45
+ * Returns a ToolError if any bundle is denied, or undefined if all are allowed.
46
+ */
47
+ export declare function requireBundlePermission(app: BlokkliApp, bundles: string[], operation: BlockPermission): ToolError | undefined;
35
48
  export {};
@@ -75,3 +75,25 @@ export function validateBundlesAllowed(app, host, bundles) {
75
75
  }
76
76
  return { valid: true };
77
77
  }
78
+ export function requireNoRestrictedAncestor(app, uuids) {
79
+ for (const uuid of uuids) {
80
+ if (app.permissions.blockHasRestrictedAncestor(uuid)) {
81
+ return {
82
+ error: "Permission denied: block is inside a parent with restricted editing permissions"
83
+ };
84
+ }
85
+ }
86
+ return void 0;
87
+ }
88
+ export function requireBundlePermission(app, bundles, operation) {
89
+ const denied = app.permissions.filterDeniedBundles(bundles, operation);
90
+ if (denied.length > 0) {
91
+ const labels = denied.map(
92
+ (b) => app.types.getBlockBundleDefinition(b)?.label || b
93
+ );
94
+ return {
95
+ error: `Permission denied: cannot ${operation} ${labels.map((l) => `"${l}"`).join(", ")}`
96
+ };
97
+ }
98
+ return void 0;
99
+ }
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { mutationResultSchema, parentSchema, positionSchema } from "../schemas.js";
4
4
  import { resolvePosition } from "../helpers.js";
5
+ import { requireBundlePermission } from "../../helpers/validation.js";
5
6
  const paramsSchema = z.object({
6
7
  itemId: z.string().describe("Content item ID from search_content results"),
7
8
  itemEntityType: z.string().describe("Entity type of the content item"),
@@ -29,6 +30,17 @@ export default defineBlokkliAgentTool({
29
30
  resultSchema: mutationResultSchema,
30
31
  requiredAdapterMethods: ["addContentSearchItem"],
31
32
  execute(ctx, params) {
33
+ const denied = requireBundlePermission(
34
+ ctx.app,
35
+ [params.targetBundle],
36
+ "add"
37
+ );
38
+ if (denied) return denied;
39
+ if (ctx.app.permissions.blockHasRestrictedAncestor(params.parent.uuid)) {
40
+ return {
41
+ error: "Permission denied: target parent is inside a block with restricted editing permissions"
42
+ };
43
+ }
32
44
  const { $t, types } = ctx.app;
33
45
  const item = {
34
46
  id: params.itemId,
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { mutationResultSchema, parentSchema, positionSchema } from "../schemas.js";
4
4
  import { resolvePosition } from "../helpers.js";
5
+ import { fragmentBlockBundle } from "#blokkli-build/config";
5
6
  const paramsSchema = z.object({
6
7
  name: z.string().describe("The fragment name to add"),
7
8
  parent: parentSchema.describe("The parent entity to add the fragment to"),
@@ -21,7 +22,17 @@ export default defineBlokkliAgentTool({
21
22
  resultSchema: mutationResultSchema,
22
23
  requiredAdapterMethods: ["fragmentsAddBlock"],
23
24
  execute(ctx, params) {
24
- const { fields, definitions } = ctx.app;
25
+ const { fields, definitions, permissions } = ctx.app;
26
+ if (!permissions.checkBlockBundlePermission(fragmentBlockBundle, "add")) {
27
+ return {
28
+ error: "Permission denied: cannot add fragment blocks."
29
+ };
30
+ }
31
+ if (permissions.blockHasRestrictedAncestor(params.parent.uuid)) {
32
+ return {
33
+ error: "Permission denied: target parent is inside a block with restricted editing permissions"
34
+ };
35
+ }
25
36
  const fragment = definitions.fragmentDefinitions.value.find(
26
37
  (f) => f.name === params.name
27
38
  );
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { mutationResultSchema, parentSchema, positionSchema } from "../schemas.js";
4
4
  import { resolvePosition } from "../helpers.js";
5
+ import { requireBundlePermission } from "../../helpers/validation.js";
5
6
  const paramsSchema = z.object({
6
7
  mediaId: z.string().describe("Media item ID from search_media results"),
7
8
  mediaBundle: z.string().describe('Media bundle type (e.g., "image")'),
@@ -25,6 +26,17 @@ export default defineBlokkliAgentTool({
25
26
  resultSchema: mutationResultSchema,
26
27
  requiredAdapterMethods: ["mediaLibraryAddBlock"],
27
28
  execute(ctx, params) {
29
+ const denied = requireBundlePermission(
30
+ ctx.app,
31
+ [params.targetBundle],
32
+ "add"
33
+ );
34
+ if (denied) return denied;
35
+ if (ctx.app.permissions.blockHasRestrictedAncestor(params.parent.uuid)) {
36
+ return {
37
+ error: "Permission denied: target parent is inside a block with restricted editing permissions"
38
+ };
39
+ }
28
40
  const { $t, types } = ctx.app;
29
41
  const item = {
30
42
  itemType: "media_library",
@@ -115,6 +115,9 @@ function validateBlockTree(ctx, blocks, allowedBundles, fieldLabel, pathPrefix)
115
115
  if (allowedBundles.length && !allowedBundles.includes(block.bundle)) {
116
116
  return `${path}: Bundle "${block.bundle}" is not allowed in field "${fieldLabel}". Allowed bundles: ${allowedBundles.join(", ")}`;
117
117
  }
118
+ if (!ctx.app.permissions.checkBlockBundlePermission(block.bundle, "add")) {
119
+ return `${path}: Permission denied: cannot add "${bundleDefinition.label}" blocks.`;
120
+ }
118
121
  const contentError = validateContentFields(ctx, block, path);
119
122
  if (contentError) return contentError;
120
123
  const optionsError = validateBlockOptions(ctx, block, path);
@@ -243,6 +246,13 @@ export default defineBlokkliAgentTool({
243
246
  error: `Field "${params.parent.field}" not found on bundle "${bundle}". Available fields: ${availableFields.length ? availableFields.join(", ") : "none"}. Use get_child_paragraphs to get the correct parent object.`
244
247
  };
245
248
  }
249
+ if (!isRootEntity) {
250
+ if (ctx.app.permissions.blockHasRestrictedAncestor(params.parent.uuid)) {
251
+ return {
252
+ error: "Permission denied: target parent is inside a block with restricted editing permissions"
253
+ };
254
+ }
255
+ }
246
256
  const validationError = validateBlockTree(
247
257
  ctx,
248
258
  params.paragraphs,
@@ -2,6 +2,7 @@ import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { mutationResultSchema, parentSchema, positionSchema } from "../schemas.js";
4
4
  import { resolvePosition } from "../helpers.js";
5
+ import { requireBundlePermission } from "../../helpers/validation.js";
5
6
  import { fromLibraryBlockBundle, itemEntityType } from "#blokkli-build/config";
6
7
  const paramsSchema = z.object({
7
8
  libraryItemUuid: z.string().describe(
@@ -26,6 +27,17 @@ export default defineBlokkliAgentTool({
26
27
  resultSchema: mutationResultSchema,
27
28
  requiredAdapterMethods: ["addLibraryItem"],
28
29
  execute(ctx, params) {
30
+ const denied = requireBundlePermission(
31
+ ctx.app,
32
+ [fromLibraryBlockBundle],
33
+ "add"
34
+ );
35
+ if (denied) return denied;
36
+ if (ctx.app.permissions.blockHasRestrictedAncestor(params.parent.uuid)) {
37
+ return {
38
+ error: "Permission denied: target parent is inside a block with restricted editing permissions"
39
+ };
40
+ }
29
41
  const { types, fields, context, blocks, $t } = ctx.app;
30
42
  const field = fields.find(params.parent.uuid, params.parent.field);
31
43
  if (!field) {
@@ -24,6 +24,11 @@ export default defineBlokkliAgentTool({
24
24
  requiredAdapterMethods: ["templatesAdd"],
25
25
  execute(ctx, params) {
26
26
  const { fields, $t } = ctx.app;
27
+ if (ctx.app.permissions.blockHasRestrictedAncestor(params.parent.uuid)) {
28
+ return {
29
+ error: "Permission denied: target parent is inside a block with restricted editing permissions"
30
+ };
31
+ }
27
32
  const field = fields.find(params.parent.uuid, params.parent.field);
28
33
  if (!field) {
29
34
  return {
@@ -1,6 +1,11 @@
1
1
  import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { runReadabilityAnalysis } from "../helpers.js";
4
+ import {
5
+ requireBundlePermission,
6
+ requireNoRestrictedAncestor
7
+ } from "../../helpers/validation.js";
8
+ import { onlyUnique } from "#blokkli/helpers";
4
9
  import Component from "./Component.vue";
5
10
  import DetailsComponent from "./Details/index.vue";
6
11
  const fieldSchema = z.object({
@@ -55,6 +60,16 @@ export default defineBlokkliAgentTool({
55
60
  buildDetails: (result) => result,
56
61
  async execute(ctx, params) {
57
62
  const { blocks, context } = ctx.app;
63
+ const bundles = params.fields.map((f) => blocks.getBlock(f.uuid)?.bundle).filter((b) => !!b).filter(onlyUnique);
64
+ if (bundles.length) {
65
+ const denied = requireBundlePermission(ctx.app, bundles, "edit");
66
+ if (denied) return denied;
67
+ }
68
+ const blockUuids = params.fields.map((f) => f.uuid).filter((uuid) => uuid !== context.value.entityUuid).filter(onlyUnique);
69
+ if (blockUuids.length) {
70
+ const ancestorDenied = requireNoRestrictedAncestor(ctx.app, blockUuids);
71
+ if (ancestorDenied) return ancestorDenied;
72
+ }
58
73
  const resolvedFields = [];
59
74
  for (const { uuid, fieldName } of params.fields) {
60
75
  let entityType;
@@ -1,6 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { mutationResultSchema } from "../schemas.js";
4
+ import {
5
+ requireBundlePermission,
6
+ requireNoRestrictedAncestor
7
+ } from "../../helpers/validation.js";
4
8
  const paramsSchema = z.object({
5
9
  uuids: z.array(z.string()).describe("The UUIDs of the paragraphs to delete")
6
10
  });
@@ -30,6 +34,14 @@ export default defineBlokkliAgentTool({
30
34
  }
31
35
  validBlocks.push({ uuid, bundle: block.bundle });
32
36
  }
37
+ const denied = requireBundlePermission(
38
+ ctx.app,
39
+ validBlocks.map((b) => b.bundle),
40
+ "delete"
41
+ );
42
+ if (denied) return denied;
43
+ const ancestorDenied = requireNoRestrictedAncestor(ctx.app, params.uuids);
44
+ if (ancestorDenied) return ancestorDenied;
33
45
  const { $t } = ctx.app;
34
46
  const firstBlock = validBlocks[0];
35
47
  const label = validBlocks.length === 1 && firstBlock ? $t("aiAgentDeleteBlockDone", "Deleted @bundle").replace(
@@ -1,6 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { mutationResultSchema } from "../schemas.js";
4
+ import {
5
+ requireBundlePermission,
6
+ requireNoRestrictedAncestor
7
+ } from "../../helpers/validation.js";
4
8
  import { fromLibraryBlockBundle } from "#blokkli-build/config";
5
9
  const paramsSchema = z.object({
6
10
  uuids: z.array(z.string()).describe("UUIDs of library paragraphs to detach")
@@ -23,6 +27,14 @@ export default defineBlokkliAgentTool({
23
27
  if (params.uuids.length === 0) {
24
28
  return { error: "No paragraph UUIDs provided" };
25
29
  }
30
+ const denied = requireBundlePermission(
31
+ ctx.app,
32
+ [fromLibraryBlockBundle],
33
+ "edit"
34
+ );
35
+ if (denied) return denied;
36
+ const ancestorDenied = requireNoRestrictedAncestor(ctx.app, params.uuids);
37
+ if (ancestorDenied) return ancestorDenied;
26
38
  for (const uuid of params.uuids) {
27
39
  const block = blocks.getBlock(uuid);
28
40
  if (!block) {
@@ -6,7 +6,9 @@ import {
6
6
  validateBlocksExist,
7
7
  validateSameField,
8
8
  validateFieldCardinality,
9
- validateBundlesAllowed
9
+ validateBundlesAllowed,
10
+ requireBundlePermission,
11
+ requireNoRestrictedAncestor
10
12
  } from "../../helpers/validation.js";
11
13
  import { getFieldKey } from "#blokkli/helpers";
12
14
  import { itemEntityType } from "#blokkli-build/config";
@@ -34,6 +36,14 @@ export default defineBlokkliAgentTool({
34
36
  const { $t, types, context, blocks } = ctx.app;
35
37
  const blocksResult = validateBlocksExist(ctx.app, params.uuids);
36
38
  if ("error" in blocksResult) return blocksResult;
39
+ const denied = requireBundlePermission(
40
+ ctx.app,
41
+ blocksResult.blocks.map((b) => b.bundle),
42
+ "add"
43
+ );
44
+ if (denied) return denied;
45
+ const ancestorDenied = requireNoRestrictedAncestor(ctx.app, params.uuids);
46
+ if (ancestorDenied) return ancestorDenied;
37
47
  if (params.parent) {
38
48
  if (!ctx.adapter.pasteExistingBlocks) {
39
49
  return {
@@ -46,6 +56,11 @@ export default defineBlokkliAgentTool({
46
56
  if (!targetBundle) {
47
57
  return { error: "Target parent not found." };
48
58
  }
59
+ if (!isRootEntity && ctx.app.permissions.blockHasRestrictedAncestor(params.parent.uuid)) {
60
+ return {
61
+ error: "Permission denied: target parent is inside a block with restricted editing permissions"
62
+ };
63
+ }
49
64
  const fieldConfig = types.getFieldConfig(
50
65
  entityType,
51
66
  targetBundle,
@@ -2,6 +2,10 @@ import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { mutationResultSchema, parentSchema, positionSchema } from "../schemas.js";
4
4
  import { resolvePosition } from "../helpers.js";
5
+ import {
6
+ requireBundlePermission,
7
+ requireNoRestrictedAncestor
8
+ } from "../../helpers/validation.js";
5
9
  const paramsSchema = z.object({
6
10
  uuids: z.array(z.string()).describe("The UUIDs of the paragraphs to move"),
7
11
  parent: parentSchema.describe("The target parent entity"),
@@ -33,6 +37,19 @@ export default defineBlokkliAgentTool({
33
37
  }
34
38
  validBlocks.push({ uuid, bundle: block.bundle });
35
39
  }
40
+ const denied = requireBundlePermission(
41
+ ctx.app,
42
+ validBlocks.map((b) => b.bundle),
43
+ "edit"
44
+ );
45
+ if (denied) return denied;
46
+ const ancestorDenied = requireNoRestrictedAncestor(ctx.app, params.uuids);
47
+ if (ancestorDenied) return ancestorDenied;
48
+ if (ctx.app.permissions.blockHasRestrictedAncestor(params.parent.uuid)) {
49
+ return {
50
+ error: "Permission denied: target parent is inside a block with restricted editing permissions"
51
+ };
52
+ }
36
53
  const { $t } = ctx.app;
37
54
  const firstBlock = validBlocks[0];
38
55
  const label = validBlocks.length === 1 && firstBlock ? $t("aiAgentMoveBlockDone", "Moved @bundle").replace(
@@ -2,6 +2,10 @@ import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { mutationResultSchema, parentSchema } from "../schemas.js";
4
4
  import { itemEntityType } from "#blokkli-build/config";
5
+ import {
6
+ requireBundlePermission,
7
+ requireNoRestrictedAncestor
8
+ } from "../../helpers/validation.js";
5
9
  const paramsSchema = z.object({
6
10
  parent: parentSchema.describe("The parent field containing the paragraphs"),
7
11
  uuids: z.array(z.string()).min(2).describe(
@@ -69,6 +73,13 @@ export default defineBlokkliAgentTool({
69
73
  };
70
74
  }
71
75
  }
76
+ const blockBundles = params.uuids.map((uuid) => blocks.getBlock(uuid)?.bundle).filter((b) => !!b);
77
+ if (blockBundles.length) {
78
+ const denied = requireBundlePermission(ctx.app, blockBundles, "edit");
79
+ if (denied) return denied;
80
+ }
81
+ const ancestorDenied = requireNoRestrictedAncestor(ctx.app, params.uuids);
82
+ if (ancestorDenied) return ancestorDenied;
72
83
  const isAlreadyInOrder = params.uuids.every(
73
84
  (uuid, i) => uuid === currentUuids[i]
74
85
  );
@@ -1,6 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { mutationResultSchema } from "../schemas.js";
4
+ import {
5
+ requireBundlePermission,
6
+ requireNoRestrictedAncestor
7
+ } from "../../helpers/validation.js";
4
8
  const paramsSchema = z.object({
5
9
  uuid: z.string().describe("The paragraph UUID containing the content reference field"),
6
10
  field: z.string().describe("The content field name (reference type)"),
@@ -30,6 +34,10 @@ export default defineBlokkliAgentTool({
30
34
  if (!block) {
31
35
  return { error: `Paragraph not found: ${params.uuid}` };
32
36
  }
37
+ const denied = requireBundlePermission(ctx.app, [block.bundle], "edit");
38
+ if (denied) return denied;
39
+ const ancestorDenied = requireNoRestrictedAncestor(ctx.app, [params.uuid]);
40
+ if (ancestorDenied) return ancestorDenied;
33
41
  const config = types.droppableFieldConfig.forName(
34
42
  ctx.itemEntityType,
35
43
  block.bundle,
@@ -1,6 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { mutationResultSchema } from "../schemas.js";
4
+ import {
5
+ requireBundlePermission,
6
+ requireNoRestrictedAncestor
7
+ } from "../../helpers/validation.js";
4
8
  const paramsSchema = z.object({
5
9
  uuid: z.string().describe("The paragraph UUID or entity UUID containing the media field"),
6
10
  field: z.string().describe("The content field name (reference type)"),
@@ -27,6 +31,12 @@ export default defineBlokkliAgentTool({
27
31
  if (!isEntity && !block) {
28
32
  return { error: `Paragraph not found: ${params.uuid}` };
29
33
  }
34
+ if (block) {
35
+ const denied = requireBundlePermission(ctx.app, [block.bundle], "edit");
36
+ if (denied) return denied;
37
+ const ancestorDenied = requireNoRestrictedAncestor(ctx.app, [params.uuid]);
38
+ if (ancestorDenied) return ancestorDenied;
39
+ }
30
40
  const entityType = isEntity ? context.value.entityType : ctx.itemEntityType;
31
41
  const bundle = isEntity ? context.value.entityBundle : block.bundle;
32
42
  const config = types.droppableFieldConfig.forName(
@@ -7,6 +7,10 @@ import {
7
7
  import { mutationResultSchema, optionValueSchema } from "../schemas.js";
8
8
  import { validateOptionValue } from "../helpers.js";
9
9
  import { onlyUnique } from "#blokkli/helpers";
10
+ import {
11
+ requireBundlePermission,
12
+ requireNoRestrictedAncestor
13
+ } from "../../helpers/validation.js";
10
14
  const paragraphOptionsSchema = z.object({
11
15
  uuid: z.string().describe("The paragraph UUID"),
12
16
  options: z.record(z.string(), optionValueSchema).describe("Options to set as key-value pairs")
@@ -43,6 +47,12 @@ export default defineBlokkliAgentTool({
43
47
  if (!block) {
44
48
  return { error: `Paragraph not found: ${blockEntry.uuid}` };
45
49
  }
50
+ const denied = requireBundlePermission(ctx.app, [block.bundle], "edit");
51
+ if (denied) return denied;
52
+ const ancestorDenied = requireNoRestrictedAncestor(ctx.app, [
53
+ blockEntry.uuid
54
+ ]);
55
+ if (ancestorDenied) return ancestorDenied;
46
56
  const bundle = block.library?.reusableBundle || block.bundle;
47
57
  const selectionItem = selection.items.value.find(
48
58
  (v) => v.uuid === blockEntry.uuid
@@ -1,6 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  import { mutationResultSchema } from "../schemas.js";
4
+ import {
5
+ requireBundlePermission,
6
+ requireNoRestrictedAncestor
7
+ } from "../../helpers/validation.js";
4
8
  const paramsSchema = z.object({
5
9
  uuidA: z.string().describe("First paragraph UUID"),
6
10
  uuidB: z.string().describe("Second paragraph UUID")
@@ -31,6 +35,17 @@ export default defineBlokkliAgentTool({
31
35
  if (!blockB) {
32
36
  return { error: `Paragraph not found: ${params.uuidB}` };
33
37
  }
38
+ const denied = requireBundlePermission(
39
+ ctx.app,
40
+ [blockA.bundle, blockB.bundle],
41
+ "edit"
42
+ );
43
+ if (denied) return denied;
44
+ const ancestorDenied = requireNoRestrictedAncestor(ctx.app, [
45
+ params.uuidA,
46
+ params.uuidB
47
+ ]);
48
+ if (ancestorDenied) return ancestorDenied;
34
49
  const fieldConfigA = types.getFieldConfig(
35
50
  blockA.host.type,
36
51
  blockA.host.bundle,
@@ -1,5 +1,10 @@
1
1
  import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
+ import {
4
+ requireBundlePermission,
5
+ requireNoRestrictedAncestor
6
+ } from "../../helpers/validation.js";
7
+ import { onlyUnique } from "#blokkli/helpers";
3
8
  import Component from "./Component.vue";
4
9
  import DetailsComponent from "./Details/index.vue";
5
10
  const operationSchema = z.object({
@@ -61,7 +66,22 @@ export default defineBlokkliAgentTool({
61
66
  component: Component,
62
67
  detailsComponent: DetailsComponent,
63
68
  buildDetails: (result) => result,
64
- execute(_ctx, params) {
69
+ execute(ctx, params) {
70
+ const blockUuids = [];
71
+ if (params.uuids) {
72
+ blockUuids.push(...Object.keys(params.uuids));
73
+ }
74
+ if (params.operations) {
75
+ blockUuids.push(...params.operations.map((op) => op.uuid));
76
+ }
77
+ const bundles = blockUuids.filter(onlyUnique).map((uuid) => ctx.app.blocks.getBlock(uuid)?.bundle).filter((b) => !!b).filter(onlyUnique);
78
+ if (bundles.length) {
79
+ const denied = requireBundlePermission(ctx.app, bundles, "edit");
80
+ if (denied) return denied;
81
+ }
82
+ const uniqueUuids = blockUuids.filter(onlyUnique);
83
+ const ancestorDenied = requireNoRestrictedAncestor(ctx.app, uniqueUuids);
84
+ if (ancestorDenied) return ancestorDenied;
65
85
  return params;
66
86
  },
67
87
  mockParams: () => ({
@@ -297,11 +297,11 @@ declare const userConversationItemSchema: z.ZodObject<{
297
297
  id: z.ZodString;
298
298
  content: z.ZodString;
299
299
  format: z.ZodEnum<{
300
+ html: "html";
300
301
  code: "code";
301
302
  markdown: "markdown";
302
- html: "html";
303
- plaintext: "plaintext";
304
303
  csv: "csv";
304
+ plaintext: "plaintext";
305
305
  }>;
306
306
  }, z.core.$strip>>>;
307
307
  }, z.core.$strip>;
@@ -326,9 +326,9 @@ declare const toolConversationItemSchema: z.ZodObject<{
326
326
  tool: z.ZodString;
327
327
  label: z.ZodString;
328
328
  status: z.ZodEnum<{
329
+ active: "active";
329
330
  success: "success";
330
331
  error: "error";
331
- active: "active";
332
332
  }>;
333
333
  }, z.core.$strip>;
334
334
  /**
@@ -370,11 +370,11 @@ export declare const conversationItemSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
370
370
  id: z.ZodString;
371
371
  content: z.ZodString;
372
372
  format: z.ZodEnum<{
373
+ html: "html";
373
374
  code: "code";
374
375
  markdown: "markdown";
375
- html: "html";
376
- plaintext: "plaintext";
377
376
  csv: "csv";
377
+ plaintext: "plaintext";
378
378
  }>;
379
379
  }, z.core.$strip>>>;
380
380
  }, z.core.$strip>, z.ZodObject<{
@@ -390,9 +390,9 @@ export declare const conversationItemSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
390
390
  tool: z.ZodString;
391
391
  label: z.ZodString;
392
392
  status: z.ZodEnum<{
393
+ active: "active";
393
394
  success: "success";
394
395
  error: "error";
395
- active: "active";
396
396
  }>;
397
397
  }, z.core.$strip>, z.ZodObject<{
398
398
  id: z.ZodString;
@@ -1,4 +1,4 @@
1
- import { B as BlokkliModule } from '../../shared/editor.BdBm1Z7C.mjs';
1
+ import { B as BlokkliModule } from '../../shared/editor.BVregnEC.mjs';
2
2
  import 'nuxt/schema';
3
3
  import 'consola';
4
4
  import '../../../dist/global/types/definitions.js';
@@ -1,4 +1,4 @@
1
- import { B as BlokkliModule } from '../../shared/editor.BdBm1Z7C.mjs';
1
+ import { B as BlokkliModule } from '../../shared/editor.BVregnEC.mjs';
2
2
  import 'nuxt/schema';
3
3
  import 'consola';
4
4
  import '../../../dist/global/types/definitions.js';