@blokkli/editor 2.0.0-alpha.59 → 2.0.0-alpha.60

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 (217) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +28 -11
  3. package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/Component.d.vue.ts +29 -0
  4. package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/Component.vue +172 -0
  5. package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/Component.vue.d.ts +29 -0
  6. package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/index.d.ts +19 -0
  7. package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/index.js +80 -0
  8. package/dist/modules/agent/runtime/app/tools/delegate_text_rewrite/Component.vue +16 -0
  9. package/dist/modules/agent/runtime/app/tools/get_all_page_content/index.js +1 -1
  10. package/dist/modules/agent/runtime/app/tools/get_content_fields/index.js +12 -9
  11. package/dist/modules/agent/runtime/app/tools/get_page_text/index.d.ts +2 -0
  12. package/dist/modules/agent/runtime/app/tools/get_page_text/index.js +65 -0
  13. package/dist/modules/agent/runtime/app/tools/get_referenced_entities/index.d.ts +2 -0
  14. package/dist/modules/agent/runtime/app/tools/get_referenced_entities/index.js +62 -0
  15. package/dist/modules/agent/runtime/app/tools/helpers.d.ts +8 -2
  16. package/dist/modules/agent/runtime/app/tools/helpers.js +9 -9
  17. package/dist/modules/agent/runtime/app/tools/schemas.d.ts +12 -0
  18. package/dist/modules/agent/runtime/app/tools/schemas.js +20 -0
  19. package/dist/modules/agent/runtime/app/tools/search_media/index.js +1 -1
  20. package/dist/modules/agent/runtime/app/tools/select_media/Component.vue +1 -1
  21. package/dist/modules/agent/runtime/server/agent.js +0 -1
  22. package/dist/modules/agent/runtime/server/classes/Session/index.js +4 -0
  23. package/dist/modules/agent/runtime/shared/toolResult.d.ts +4 -0
  24. package/dist/modules/agent/runtime/shared/toolResult.js +5 -0
  25. package/dist/modules/drupal/graphql/features/notifications.graphql +39 -0
  26. package/dist/modules/drupal/index.mjs +6 -1
  27. package/dist/modules/drupal/runtime/adapter/index.js +38 -0
  28. package/dist/runtime/editor/components/Actions/ItemDropdown/Item.vue +0 -1
  29. package/dist/runtime/editor/components/Actions/ScrollArrow/index.d.vue.ts +13 -0
  30. package/dist/runtime/editor/components/Actions/ScrollArrow/index.vue +52 -0
  31. package/dist/runtime/editor/components/Actions/ScrollArrow/index.vue.d.ts +13 -0
  32. package/dist/runtime/editor/components/Actions/Title/index.vue +2 -2
  33. package/dist/runtime/editor/components/Actions/index.vue +47 -7
  34. package/dist/runtime/editor/components/Actions/useToolbarScroll.d.ts +25 -0
  35. package/dist/runtime/editor/components/Actions/useToolbarScroll.js +125 -0
  36. package/dist/runtime/editor/components/AddListItem/index.vue +0 -2
  37. package/dist/runtime/editor/components/AppMenu/MenuButton.vue +1 -3
  38. package/dist/runtime/editor/components/ArtboardTooltip/index.vue +4 -1
  39. package/dist/runtime/editor/components/Avatar/index.vue +0 -1
  40. package/dist/runtime/editor/components/BlockPreviewRenderer/index.d.vue.ts +1 -1
  41. package/dist/runtime/editor/components/BlockPreviewRenderer/index.vue.d.ts +1 -1
  42. package/dist/runtime/editor/components/BundleSelector/index.vue +0 -4
  43. package/dist/runtime/editor/components/Dialog/index.d.vue.ts +2 -2
  44. package/dist/runtime/editor/components/Dialog/index.vue +1 -3
  45. package/dist/runtime/editor/components/Dialog/index.vue.d.ts +2 -2
  46. package/dist/runtime/editor/components/DiffApproval/Highlight/Item.d.vue.ts +8 -0
  47. package/dist/runtime/editor/components/DiffApproval/Highlight/Item.vue +12 -2
  48. package/dist/runtime/editor/components/DiffApproval/Highlight/Item.vue.d.ts +8 -0
  49. package/dist/runtime/editor/components/DiffApproval/Highlight/index.d.vue.ts +8 -0
  50. package/dist/runtime/editor/components/DiffApproval/Highlight/index.vue +14 -2
  51. package/dist/runtime/editor/components/DiffApproval/Highlight/index.vue.d.ts +8 -0
  52. package/dist/runtime/editor/components/DiffApproval/Toolbar/index.d.vue.ts +2 -2
  53. package/dist/runtime/editor/components/DiffApproval/Toolbar/index.vue +0 -2
  54. package/dist/runtime/editor/components/DiffApproval/Toolbar/index.vue.d.ts +2 -2
  55. package/dist/runtime/editor/components/DiffApproval/index.vue +1 -0
  56. package/dist/runtime/editor/components/Form/Datepicker/index.vue +0 -1
  57. package/dist/runtime/editor/components/Form/TextDark/index.vue +0 -1
  58. package/dist/runtime/editor/components/Form/Textarea/index.vue +0 -1
  59. package/dist/runtime/editor/components/Form/Toggle/index.d.vue.ts +1 -0
  60. package/dist/runtime/editor/components/Form/Toggle/index.vue +9 -2
  61. package/dist/runtime/editor/components/Form/Toggle/index.vue.d.ts +1 -0
  62. package/dist/runtime/editor/components/FormOverlay/index.vue +0 -1
  63. package/dist/runtime/editor/components/Icon/index.vue +0 -2
  64. package/dist/runtime/editor/components/Messages/Item/index.vue +4 -1
  65. package/dist/runtime/editor/components/Messages/index.vue +3 -0
  66. package/dist/runtime/editor/components/Panel/Sheet/index.vue +1 -1
  67. package/dist/runtime/editor/components/Popup/index.vue +0 -2
  68. package/dist/runtime/editor/components/RichText/Editor/index.d.vue.ts +1 -1
  69. package/dist/runtime/editor/components/RichText/Editor/index.vue.d.ts +1 -1
  70. package/dist/runtime/editor/components/ScheduleDate/index.vue +1 -3
  71. package/dist/runtime/editor/components/SearchOverlay/index.d.vue.ts +1 -1
  72. package/dist/runtime/editor/components/SearchOverlay/index.vue.d.ts +1 -1
  73. package/dist/runtime/editor/components/Toolbar/ViewOptions/List/Button/index.d.vue.ts +3 -0
  74. package/dist/runtime/editor/components/Toolbar/ViewOptions/List/Button/index.vue +74 -0
  75. package/dist/runtime/editor/components/Toolbar/ViewOptions/List/Button/index.vue.d.ts +3 -0
  76. package/dist/runtime/editor/components/Toolbar/ViewOptions/List/index.d.vue.ts +7 -0
  77. package/dist/runtime/editor/components/Toolbar/ViewOptions/List/index.vue +16 -0
  78. package/dist/runtime/editor/components/Toolbar/ViewOptions/List/index.vue.d.ts +7 -0
  79. package/dist/runtime/editor/components/Toolbar/ViewOptions/index.d.vue.ts +3 -0
  80. package/dist/runtime/editor/components/Toolbar/ViewOptions/index.vue +57 -0
  81. package/dist/runtime/editor/components/Toolbar/ViewOptions/index.vue.d.ts +3 -0
  82. package/dist/runtime/editor/components/Toolbar/index.vue +3 -56
  83. package/dist/runtime/editor/components/ToolbarDropdown/index.d.vue.ts +21 -0
  84. package/dist/runtime/editor/components/ToolbarDropdown/index.vue +36 -0
  85. package/dist/runtime/editor/components/ToolbarDropdown/index.vue.d.ts +21 -0
  86. package/dist/runtime/editor/components/Tooltip/Context.vue +3 -1
  87. package/dist/runtime/editor/components/Tooltip/index.d.vue.ts +1 -1
  88. package/dist/runtime/editor/components/Tooltip/index.vue +4 -1
  89. package/dist/runtime/editor/components/Tooltip/index.vue.d.ts +1 -1
  90. package/dist/runtime/editor/components/index.d.ts +1 -0
  91. package/dist/runtime/editor/components/index.js +1 -0
  92. package/dist/runtime/editor/composables/defineViewOption.d.ts +5 -0
  93. package/dist/runtime/editor/composables/defineViewOption.js +10 -0
  94. package/dist/runtime/editor/composables/index.d.ts +3 -0
  95. package/dist/runtime/editor/composables/index.js +2 -0
  96. package/dist/runtime/editor/composables/useDismiss.d.ts +30 -0
  97. package/dist/runtime/editor/composables/useDismiss.js +43 -0
  98. package/dist/runtime/editor/composables/useGlobalBlokkliObject.d.ts +3 -3
  99. package/dist/runtime/editor/css/output.css +1 -1
  100. package/dist/runtime/editor/events/index.d.ts +23 -0
  101. package/dist/runtime/editor/features/add-list/Actions/index.vue +0 -1
  102. package/dist/runtime/editor/features/add-list/Blocks/index.vue +0 -1
  103. package/dist/runtime/editor/features/add-list/Help/Item.vue +2 -7
  104. package/dist/runtime/editor/features/add-list/Help/index.vue +1 -1
  105. package/dist/runtime/editor/features/add-list/index.vue +0 -2
  106. package/dist/runtime/editor/features/anchors/index.vue +11 -11
  107. package/dist/runtime/editor/features/anchors/types.d.ts +1 -0
  108. package/dist/runtime/editor/features/anchors/types.js +1 -0
  109. package/dist/runtime/editor/features/artboard/Renderer.vue +30 -28
  110. package/dist/runtime/editor/features/block-scheduler/Dialog/ScheduleSection.vue +0 -3
  111. package/dist/runtime/editor/features/block-scheduler/index.vue +0 -1
  112. package/dist/runtime/editor/features/block-transfer/SummaryDialog/index.vue +0 -4
  113. package/dist/runtime/editor/features/breadcrumbs/Crumb/index.vue +0 -5
  114. package/dist/runtime/editor/features/changelog/changelog.json +8 -0
  115. package/dist/runtime/editor/features/command-palette/Palette/Item/index.vue +0 -3
  116. package/dist/runtime/editor/features/command-palette/Palette/index.vue +0 -1
  117. package/dist/runtime/editor/features/comments/AddForm/index.vue +0 -1
  118. package/dist/runtime/editor/features/comments/Comment/Actions/index.vue +0 -4
  119. package/dist/runtime/editor/features/comments/Comment/index.d.vue.ts +14 -0
  120. package/dist/runtime/editor/features/comments/Comment/index.vue +29 -8
  121. package/dist/runtime/editor/features/comments/Comment/index.vue.d.ts +14 -0
  122. package/dist/runtime/editor/features/comments/CommentInput/index.d.vue.ts +1 -1
  123. package/dist/runtime/editor/features/comments/CommentInput/index.vue +0 -3
  124. package/dist/runtime/editor/features/comments/CommentInput/index.vue.d.ts +1 -1
  125. package/dist/runtime/editor/features/comments/Sidebar/AddForm/index.vue +0 -1
  126. package/dist/runtime/editor/features/comments/Sidebar/index.d.vue.ts +16 -0
  127. package/dist/runtime/editor/features/comments/Sidebar/index.vue +13 -8
  128. package/dist/runtime/editor/features/comments/Sidebar/index.vue.d.ts +16 -0
  129. package/dist/runtime/editor/features/comments/Thread/ReplyForm/index.vue +0 -1
  130. package/dist/runtime/editor/features/comments/Thread/index.d.vue.ts +16 -0
  131. package/dist/runtime/editor/features/comments/Thread/index.vue +26 -6
  132. package/dist/runtime/editor/features/comments/Thread/index.vue.d.ts +16 -0
  133. package/dist/runtime/editor/features/comments/index.vue +28 -3
  134. package/dist/runtime/editor/features/delete/types.d.ts +1 -0
  135. package/dist/runtime/editor/features/delete/types.js +1 -0
  136. package/dist/runtime/editor/features/dev-mode/index.vue +17 -15
  137. package/dist/runtime/editor/features/dragging-overlay/DragItems/index.vue +1 -0
  138. package/dist/runtime/editor/features/duplicate/types.d.ts +1 -0
  139. package/dist/runtime/editor/features/duplicate/types.js +1 -0
  140. package/dist/runtime/editor/features/editable-field/Overlay/Frame/index.vue +0 -2
  141. package/dist/runtime/editor/features/editable-field/Overlay/Plaintext/index.vue +0 -1
  142. package/dist/runtime/editor/features/editable-field/Overlay/ReadabilityIndicator/index.vue +0 -5
  143. package/dist/runtime/editor/features/editable-field/Overlay/index.vue +0 -5
  144. package/dist/runtime/editor/features/editable-mask/index.vue +21 -20
  145. package/dist/runtime/editor/features/entity-title/index.vue +0 -4
  146. package/dist/runtime/editor/features/fragments/Dialog/index.vue +0 -4
  147. package/dist/runtime/editor/features/grid/index.vue +16 -15
  148. package/dist/runtime/editor/features/grid/types.d.ts +1 -0
  149. package/dist/runtime/editor/features/grid/types.js +1 -0
  150. package/dist/runtime/editor/features/help/Dialog/index.d.vue.ts +7 -0
  151. package/dist/runtime/editor/features/help/Dialog/index.vue +57 -0
  152. package/dist/runtime/editor/features/help/Dialog/index.vue.d.ts +7 -0
  153. package/dist/runtime/editor/features/help/index.vue +52 -47
  154. package/dist/runtime/editor/features/history/List/index.vue +2 -9
  155. package/dist/runtime/editor/features/history/types.d.ts +1 -0
  156. package/dist/runtime/editor/features/history/types.js +1 -0
  157. package/dist/runtime/editor/features/notifications/Item/index.d.vue.ts +4 -0
  158. package/dist/runtime/editor/features/notifications/Item/index.vue +96 -0
  159. package/dist/runtime/editor/features/notifications/Item/index.vue.d.ts +4 -0
  160. package/dist/runtime/editor/features/notifications/List/index.d.vue.ts +11 -0
  161. package/dist/runtime/editor/features/notifications/List/index.vue +126 -0
  162. package/dist/runtime/editor/features/notifications/List/index.vue.d.ts +11 -0
  163. package/dist/runtime/editor/features/notifications/docs.md +12 -0
  164. package/dist/runtime/editor/features/notifications/index.d.vue.ts +3 -0
  165. package/dist/runtime/editor/features/notifications/index.vue +123 -0
  166. package/dist/runtime/editor/features/notifications/index.vue.d.ts +3 -0
  167. package/dist/runtime/editor/features/notifications/types.d.ts +132 -0
  168. package/dist/runtime/editor/features/notifications/types.js +20 -0
  169. package/dist/runtime/editor/features/options/Form/Checkbox/index.vue +6 -2
  170. package/dist/runtime/editor/features/options/Form/Checkboxes/index.vue +14 -4
  171. package/dist/runtime/editor/features/options/Form/Color/index.vue +1 -1
  172. package/dist/runtime/editor/features/options/Form/ComplexType/index.vue +0 -1
  173. package/dist/runtime/editor/features/options/Form/DateTimeLocal/index.vue +0 -1
  174. package/dist/runtime/editor/features/options/Form/Group.vue +3 -1
  175. package/dist/runtime/editor/features/options/Form/Item.vue +1 -2
  176. package/dist/runtime/editor/features/options/Form/Number/index.vue +9 -3
  177. package/dist/runtime/editor/features/options/Form/Radios/index.vue +3 -2
  178. package/dist/runtime/editor/features/options/Form/Range/index.vue +8 -2
  179. package/dist/runtime/editor/features/options/Form/Text/index.vue +6 -2
  180. package/dist/runtime/editor/features/options/index.vue +7 -1
  181. package/dist/runtime/editor/features/ownership/Banner/index.vue +3 -1
  182. package/dist/runtime/editor/features/ownership/types.d.ts +1 -0
  183. package/dist/runtime/editor/features/ownership/types.js +1 -0
  184. package/dist/runtime/editor/features/preview-grant/types.d.ts +1 -0
  185. package/dist/runtime/editor/features/preview-grant/types.js +1 -0
  186. package/dist/runtime/editor/features/proxy-view/index.vue +24 -21
  187. package/dist/runtime/editor/features/publish/Dialog/PublishOption.vue +0 -2
  188. package/dist/runtime/editor/features/publish/Dialog/index.vue +1 -2
  189. package/dist/runtime/editor/features/responsive-preview/Frame/index.vue +0 -1
  190. package/dist/runtime/editor/features/revert/types.d.ts +1 -0
  191. package/dist/runtime/editor/features/revert/types.js +1 -0
  192. package/dist/runtime/editor/features/settings/Dialog/FeatureSetting/index.vue +18 -8
  193. package/dist/runtime/editor/features/swap/types.d.ts +1 -0
  194. package/dist/runtime/editor/features/swap/types.js +1 -0
  195. package/dist/runtime/editor/features/translations/Banner/index.vue +4 -1
  196. package/dist/runtime/editor/features/translations/CsvDialog/Import/index.vue +4 -1
  197. package/dist/runtime/editor/features/translations/TranslateDialog/index.vue +7 -2
  198. package/dist/runtime/editor/plugins/BlockIndicator/index.vue +0 -2
  199. package/dist/runtime/editor/plugins/ContextMenu/Menu/index.vue +4 -36
  200. package/dist/runtime/editor/plugins/ItemAction/index.vue +0 -1
  201. package/dist/runtime/editor/plugins/Sidebar/index.vue +7 -50
  202. package/dist/runtime/editor/plugins/ToolbarButton/index.d.vue.ts +8 -2
  203. package/dist/runtime/editor/plugins/ToolbarButton/index.vue +122 -28
  204. package/dist/runtime/editor/plugins/ToolbarButton/index.vue.d.ts +8 -2
  205. package/dist/runtime/editor/plugins/index.d.ts +1 -2
  206. package/dist/runtime/editor/plugins/index.js +1 -3
  207. package/dist/runtime/editor/providers/fieldValue.js +11 -13
  208. package/dist/runtime/editor/providers/plugin.d.ts +12 -0
  209. package/dist/runtime/editor/providers/plugin.js +9 -0
  210. package/dist/runtime/editor/translations/de.json +51 -19
  211. package/dist/runtime/editor/translations/fr.json +16 -4
  212. package/dist/runtime/editor/translations/gsw_CH.json +44 -19
  213. package/dist/runtime/editor/translations/it.json +16 -4
  214. package/package.json +4 -5
  215. package/dist/runtime/editor/plugins/ViewOption/index.d.vue.ts +0 -139
  216. package/dist/runtime/editor/plugins/ViewOption/index.vue +0 -99
  217. package/dist/runtime/editor/plugins/ViewOption/index.vue.d.ts +0 -139
@@ -77,8 +77,14 @@ export declare function resolveHost(app: BlokkliApp, uuid: string): {
77
77
  */
78
78
  export declare function getResolvedOptions(app: BlokkliApp, bundleOrBlock: Parameters<BlokkliApp['definitions']['getBlockDefinition']>[0], fieldListType: Parameters<BlokkliApp['definitions']['getBlockDefinition']>[1], parentBundle: Parameters<BlokkliApp['definitions']['getBlockDefinition']>[2]): OptionItem[] | null;
79
79
  /**
80
- * Read every editable content field of a block (or entity), skipping fields
81
- * with no resolvable type. Callers map the result into their own output shape.
80
+ * Read every editable content field of a block (or entity), skipping `table`
81
+ * fields (no text payload). Iterates the declared `editableFieldConfig` rather
82
+ * than the runtime `v-blokkli-editable` directive registry — the former is the
83
+ * canonical declaration (it sees fields exposed via `propsFieldMapping` even
84
+ * when no directive is present in the template), while the latter only sees
85
+ * fields whose template marks them with the directive. `fieldValue.readValue`
86
+ * already knows how to resolve a value through `propsFieldMapping`, so this
87
+ * one swap surfaces all editable fields to every caller.
82
88
  */
83
89
  export declare function readBlockContentFields(app: BlokkliApp, uuid: string, entityType: string, bundle: string): Array<{
84
90
  fieldName: string;
@@ -257,21 +257,21 @@ export function getResolvedOptions(app, bundleOrBlock, fieldListType, parentBund
257
257
  }
258
258
  export function readBlockContentFields(app, uuid, entityType, bundle) {
259
259
  const result = [];
260
- for (const editable of app.directive.getEditablesForBlock(uuid)) {
261
- const fieldType = app.fieldValue.resolveFieldType(
262
- entityType,
263
- bundle,
264
- editable.fieldName
265
- );
266
- if (!fieldType) continue;
260
+ const configs = app.types.editableFieldConfig.forEntityTypeAndBundle(
261
+ entityType,
262
+ bundle
263
+ );
264
+ for (const cfg of configs) {
265
+ if (cfg.type === "table") continue;
266
+ const fieldType = cfg.type === "frame" || cfg.type === "markup" ? "markup" : "plain";
267
267
  const value = app.fieldValue.readValue(
268
268
  entityType,
269
269
  uuid,
270
270
  bundle,
271
- editable.fieldName,
271
+ cfg.name,
272
272
  fieldType
273
273
  );
274
- result.push({ fieldName: editable.fieldName, fieldType, value });
274
+ result.push({ fieldName: cfg.name, fieldType, value });
275
275
  }
276
276
  return result;
277
277
  }
@@ -60,6 +60,18 @@ export declare const mutationResultSchema: z.ZodUnion<readonly [z.ZodObject<{
60
60
  * a single string is accepted as a fallback.
61
61
  */
62
62
  export declare function stringArrayParam(description: string): z.ZodPipe<z.ZodTransform<unknown, unknown>, z.ZodArray<z.ZodString>>;
63
+ /**
64
+ * Wraps an object params schema to tolerate a singular key when the schema
65
+ * actually expects its plural form (e.g. `uuid` → `uuids`). LLMs — especially
66
+ * the smaller models — frequently pick the singular form when a tool
67
+ * description mentions both ("one or more UUIDs"). Without this, the call
68
+ * fails validation and the model often retries with the same wrong key.
69
+ *
70
+ * The generated JSON Schema is unchanged (the wrapping happens via
71
+ * `z.preprocess`), so the model is still guided to the plural form; the
72
+ * singular form is silently accepted as a fallback.
73
+ */
74
+ export declare function tolerantSingularKeys<T extends z.ZodType>(schema: T, aliases: Record<string, string>): z.ZodPipe<z.ZodTransform<unknown, unknown>, T>;
63
75
  /**
64
76
  * Shared schema for option values (used by add_blocks and set_block_options).
65
77
  */
@@ -39,6 +39,26 @@ export function stringArrayParam(description) {
39
39
  z.array(z.string()).describe(description)
40
40
  );
41
41
  }
42
+ export function tolerantSingularKeys(schema, aliases) {
43
+ return z.preprocess((value) => {
44
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
45
+ return value;
46
+ }
47
+ const obj = value;
48
+ const remapped = {};
49
+ let touched = false;
50
+ for (const key of Object.keys(obj)) {
51
+ const plural = aliases[key];
52
+ if (plural && !(plural in obj)) {
53
+ remapped[plural] = obj[key];
54
+ touched = true;
55
+ } else {
56
+ remapped[key] = obj[key];
57
+ }
58
+ }
59
+ return touched ? remapped : obj;
60
+ }, schema);
61
+ }
42
62
  export const optionValueSchema = z.union([
43
63
  z.string(),
44
64
  z.boolean(),
@@ -2,7 +2,7 @@ import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
3
  const paramsSchema = z.object({
4
4
  query: z.string().optional().describe(
5
- "Search text to filter media items. Omit or leave empty to list all available media."
5
+ 'Search text to filter media items. Searching for "foobar test" will search the exact full string, so prefer searching single for words.'
6
6
  ),
7
7
  bundle: z.string().optional().describe('Media bundle filter (e.g., "image", "video")')
8
8
  });
@@ -14,7 +14,7 @@
14
14
  @click="selectedId = item.mediaId"
15
15
  >
16
16
  <div
17
- class="_bk_w-40 _bk_h-40 _bk_bg-mono-100 _bk_rounded _bk_overflow-hidden _bk_shrink-0 _bk_flex _bk_items-center _bk_justify-center"
17
+ class="_bk_size-100 _bk_bg-mono-100 _bk_rounded _bk_overflow-hidden _bk_shrink-0 _bk_flex _bk_items-center _bk_justify-center"
18
18
  :class="{
19
19
  '_bk_outline _bk_outline-accent-700 _bk_relative _bk_z-40': selectedId === item.mediaId
20
20
  }"
@@ -58,7 +58,6 @@ export default defineWebSocketHandler({
58
58
  case "init":
59
59
  case "accept":
60
60
  case "reject":
61
- case "new_conversation":
62
61
  case "restore_conversation":
63
62
  send(peer, {
64
63
  type: "error",
@@ -231,6 +231,10 @@ export class Session {
231
231
  }
232
232
  newConversation(peer, authSecret) {
233
233
  this.abortController?.abort();
234
+ for (const pending of this.pendingToolCalls.values()) {
235
+ pending.reject(new Error("Cancelled"));
236
+ }
237
+ this.pendingToolCalls.clear();
234
238
  this.history.clear();
235
239
  this.lastTools = [];
236
240
  this.lastDebugPayload = null;
@@ -89,6 +89,10 @@ export declare class ToolResult {
89
89
  /**
90
90
  * Stale form: a volatile query whose data is outdated because a mutation
91
91
  * happened after it. Pure and idempotent.
92
+ *
93
+ * Error results are preserved verbatim — a failed call isn't "stale data",
94
+ * it's a failure the LLM may still need to act on (e.g. fix its input and
95
+ * retry). Collapsing it to a generic stale summary hides the cause.
92
96
  */
93
97
  stale(): ToolResult;
94
98
  }
@@ -145,9 +145,14 @@ export class ToolResult {
145
145
  /**
146
146
  * Stale form: a volatile query whose data is outdated because a mutation
147
147
  * happened after it. Pure and idempotent.
148
+ *
149
+ * Error results are preserved verbatim — a failed call isn't "stale data",
150
+ * it's a failure the LLM may still need to act on (e.g. fix its input and
151
+ * retry). Collapsing it to a generic stale summary hides the cause.
148
152
  */
149
153
  stale() {
150
154
  if (this.envelope.kind === "stale") return this;
155
+ if (this.envelope.kind === "error") return this;
151
156
  return ToolResult.fromWire(
152
157
  JSON.stringify({ stale: true, summary: this.staleSummary })
153
158
  );
@@ -0,0 +1,39 @@
1
+ fragment paragraphsBlokkliNotification on ParagraphsBlokkliNotification {
2
+ uuid
3
+ type
4
+ read
5
+ created
6
+ title
7
+ message
8
+ relatedEntityUuid
9
+ user {
10
+ id
11
+ name
12
+ imageUrl
13
+ }
14
+ host {
15
+ entityType
16
+ entityUuid
17
+ entityBundle
18
+ label
19
+ url
20
+ }
21
+ }
22
+
23
+ query pbGetNotifications($after: String, $markAsRead: Boolean) {
24
+ result: pbGetNotifications(after: $after, markAsRead: $markAsRead) {
25
+ items {
26
+ ...paragraphsBlokkliNotification
27
+ }
28
+ unreadCount
29
+ nextCursor
30
+ }
31
+ }
32
+
33
+ query pbGetNotificationCount {
34
+ count: pbGetNotificationCount
35
+ }
36
+
37
+ mutation pbMarkNotificationsAsRead($uuids: [String!]) {
38
+ count: pbMarkNotificationsAsRead(uuids: $uuids)
39
+ }
@@ -163,11 +163,16 @@ export declare const templateEditRouteName: string|null
163
163
  }
164
164
  addMutation("ignore_analyze");
165
165
  addMutation("unignore_analyze");
166
- if (graphql.schemaHasType("CommentBlokkliNode")) {
166
+ if (graphql.schemaHasType("ParagraphsBlokkliComment")) {
167
167
  addGraphqlDocument("features/comments.graphql");
168
168
  } else {
169
169
  context.features.disableFeature("comments");
170
170
  }
171
+ if (queryFields.has("pbGetNotifications") && queryFields.has("pbGetNotificationCount") && mutationFields.has("pbMarkNotificationsAsRead")) {
172
+ addGraphqlDocument("features/notifications.graphql");
173
+ } else {
174
+ context.features.disableFeature("notifications");
175
+ }
171
176
  if (mutationFields.has("paragraphsBlokkliAgentToken")) {
172
177
  addGraphqlDocument("features/agent.graphql");
173
178
  } else {
@@ -13,6 +13,7 @@ import {
13
13
  useRouter
14
14
  } from "#imports";
15
15
  import { ParagraphsBlokkliRemoteVideoProvider } from "#graphql-operations";
16
+ import { toValidNotificationType } from "#blokkli/editor/features/notifications/types";
16
17
  function mapBlokkliUser(user) {
17
18
  if (!user) {
18
19
  return null;
@@ -775,6 +776,43 @@ export default defineBlokkliEditAdapter(
775
776
  return updated;
776
777
  });
777
778
  }
779
+ if (hasQuery("pbGetNotifications")) {
780
+ adapter.loadNotifications = (options) => useGraphqlQuery("pbGetNotifications", {
781
+ after: options.after,
782
+ markAsRead: options.markAsRead
783
+ }).then((v) => {
784
+ const result = v.data.result;
785
+ return {
786
+ items: (result?.items ?? []).map((item) => ({
787
+ uuid: item.uuid,
788
+ type: toValidNotificationType(item.type),
789
+ read: item.read,
790
+ created: item.created,
791
+ title: item.title,
792
+ message: item.message ?? void 0,
793
+ relatedEntityUuid: item.relatedEntityUuid ?? void 0,
794
+ user: mapBlokkliUser(item.user),
795
+ host: item.host ? {
796
+ uuid: item.host.entityUuid,
797
+ entityType: item.host.entityType,
798
+ entityBundle: item.host.entityBundle,
799
+ label: item.host.label ?? "",
800
+ url: item.host.url ?? ""
801
+ } : null
802
+ })),
803
+ nextCursor: result?.nextCursor ?? null,
804
+ unreadCount: result?.unreadCount ?? 0
805
+ };
806
+ });
807
+ }
808
+ if (hasQuery("pbGetNotificationCount")) {
809
+ adapter.loadUnreadNotificationsCount = () => useGraphqlQuery("pbGetNotificationCount").then((v) => v.data.count ?? 0);
810
+ }
811
+ if (hasMutation("pbMarkNotificationsAsRead")) {
812
+ adapter.markAllNotificationsAsRead = () => useGraphqlMutation("pbMarkNotificationsAsRead", {
813
+ uuids: void 0
814
+ }).then((v) => v.data.count);
815
+ }
778
816
  if (hasQuery("pbReferencedEntities")) {
779
817
  adapter.getReferencedEntities = (uuids) => useGraphqlQuery("pbReferencedEntities", {
780
818
  ...ctx.value,
@@ -1,6 +1,5 @@
1
1
  <template>
2
2
  <button
3
- :data-test="`item-dropdown-action-${action.id}`"
4
3
  class="_bk_gap-10 _bk_group/tooltip _bk_grid _bk_grid-cols-[20px_1fr] _bk_w-full _bk_text-mono-300 _bk_items-center _bk_left-left _bk_leading-none _bk_disabled:opacity-20 _bk_disabled:pointer-events-none _bk_hover:text-white _bk_hover:bg-mono-800 _bk_px-10"
5
4
  :class="{
6
5
  '_bk_hover:bg-orange-normal/10! _bk_hover:text-orange-light!': action.variant === 'agent',
@@ -0,0 +1,13 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: import("vue").DefineComponent<{
4
+ side: "left" | "right";
5
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ end: () => any;
7
+ start: () => any;
8
+ }, string, import("vue").PublicProps, Readonly<{
9
+ side: "left" | "right";
10
+ }> & Readonly<{
11
+ onEnd?: (() => any) | undefined;
12
+ onStart?: (() => any) | undefined;
13
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -0,0 +1,52 @@
1
+ <template>
2
+ <button
3
+ type="button"
4
+ class="_bk_hidden _bk_lg:flex _bk_absolute _bk_top-1 _bk_bottom-1 _bk_z-actions _bk_w-40 _bk_cursor-pointer _bk_bg-mono-950/90 _bk_hover:bg-mono-700 _bk_items-center _bk_justify-center"
5
+ :class="
6
+ side === 'left' ? '_bk_left-0 _bk_border-r _bk_border-r-mono-700' : '_bk_right-0 _bk_border-l _bk_border-l-mono-700'
7
+ "
8
+ @pointerdown="onPointerDown"
9
+ >
10
+ <Icon
11
+ :name="
12
+ side === 'left' ? 'bk_mdi_chevron_backward' : 'bk_mdi_chevron_forward'
13
+ "
14
+ class="_bk_fill-current _bk_pointer-events-none _bk_size-30"
15
+ />
16
+ </button>
17
+ </template>
18
+
19
+ <script setup>
20
+ import { onBeforeUnmount } from "#imports";
21
+ import { Icon } from "#blokkli/editor/components";
22
+ defineProps({
23
+ side: { type: String, required: true }
24
+ });
25
+ const emit = defineEmits(["start", "end"]);
26
+ let isPressed = false;
27
+ function onRelease() {
28
+ if (!isPressed) {
29
+ return;
30
+ }
31
+ isPressed = false;
32
+ window.removeEventListener("pointerup", onRelease);
33
+ window.removeEventListener("pointercancel", onRelease);
34
+ emit("end");
35
+ }
36
+ function onPointerDown() {
37
+ if (isPressed) {
38
+ return;
39
+ }
40
+ isPressed = true;
41
+ window.addEventListener("pointerup", onRelease);
42
+ window.addEventListener("pointercancel", onRelease);
43
+ emit("start");
44
+ }
45
+ onBeforeUnmount(onRelease);
46
+ </script>
47
+
48
+ <script>
49
+ export default {
50
+ name: "ActionsScrollArrow"
51
+ };
52
+ </script>
@@ -0,0 +1,13 @@
1
+ declare const _default: typeof __VLS_export;
2
+ export default _default;
3
+ declare const __VLS_export: import("vue").DefineComponent<{
4
+ side: "left" | "right";
5
+ }, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
6
+ end: () => any;
7
+ start: () => any;
8
+ }, string, import("vue").PublicProps, Readonly<{
9
+ side: "left" | "right";
10
+ }> & Readonly<{
11
+ onEnd?: (() => any) | undefined;
12
+ onStart?: (() => any) | undefined;
13
+ }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
@@ -7,7 +7,6 @@
7
7
  }"
8
8
  >
9
9
  <button
10
- data-test="item-actions-dropdown-toggle"
11
10
  class="bk-blokkli-item-actions-type-button bk-item-icon-hover-parent _bk_group/tooltip _bk_pl-10 _bk_pr-3 _bk_flex _bk_items-center _bk_lg:min-w-[180px] _bk_text-mono-300 _bk_font-bold _bk_h-full _bk_leading-none _bk_relative _bk_w-full _bk_cursor-pointer _bk_hover:text-mono-50 _bk_hover:bg-mono-700"
12
11
  tabindex="-1"
13
12
  :class="{
@@ -106,7 +105,7 @@
106
105
  </template>
107
106
 
108
107
  <script setup>
109
- import { watch, computed, useBlokkli } from "#imports";
108
+ import { watch, computed, nextTick, useBlokkli } from "#imports";
110
109
  import { falsy } from "#blokkli/helpers";
111
110
  import {
112
111
  Icon,
@@ -147,6 +146,7 @@ async function onToggleDropdown() {
147
146
  const willOpen = !showDropdown.value;
148
147
  if (willOpen) {
149
148
  await ui.flushPendingChanges();
149
+ await nextTick();
150
150
  }
151
151
  showDropdown.value = willOpen;
152
152
  }
@@ -2,19 +2,27 @@
2
2
  <div
3
3
  ref="el"
4
4
  :style="{
5
- visibility: isVisible ? 'visible' : 'hidden'
5
+ visibility: isVisible ? 'visible' : 'hidden',
6
+ '--bk-actions-max-width': `${paddedViewportWidth}px`
6
7
  }"
7
8
  class="bk bk-blokkli-item-actions-inner _bk_absolute _bk_left-0 _bk_p-0 _bk_z-actions _bk_w-full _bk_text-mono-50 _bk_select-none _bk_text-sm _bk_pointer-events-auto"
8
9
  @mouseleave="onMouseLeave"
9
10
  @mouseenter="onMouseEnter"
10
11
  >
12
+ <ScrollArrow
13
+ v-show="showLeft"
14
+ side="left"
15
+ @start="startScroll(-1)"
16
+ @end="stopScroll"
17
+ />
11
18
  <div
12
19
  id="bk-blokkli-item-actions-controls"
13
- ref="controlsEl"
14
- class="bk-blokkli-item-actions-controls _bk_flex _bk_items-stretch _bk_whitespace-nowrap _bk_h-full _bk_flex-wrap _bk_lg:flex-nowrap _bk_bg-mono-950/90 _bk_scheme-dark _bk_relative _bk_z-50 _bk_lg:border _bk_lg:border-mono-400 _bk_lg:bg-mono-900"
20
+ ref="contentEl"
21
+ class="bk-blokkli-item-actions-controls _bk_flex _bk_items-stretch _bk_whitespace-nowrap _bk_h-full _bk_flex-wrap _bk_lg:flex-nowrap _bk_lg:w-max _bk_bg-mono-950/90 _bk_scheme-dark _bk_relative _bk_z-50 _bk_lg:border _bk_lg:border-mono-400 _bk_lg:bg-mono-900"
15
22
  :class="{
16
23
  '_bk_pointer-events-none': ui.isTransforming.value
17
24
  }"
25
+ :style="{ '--bk-actions-scroll-x': `${-scrollX}px` }"
18
26
  >
19
27
  <Interactions />
20
28
  <Title />
@@ -25,6 +33,12 @@
25
33
  class="_bk_relative _bk_flex _bk_flex-1 _bk_lg:flex-initial _bk_lg:border-l _bk_lg:border-l-mono-500 _bk_justify-end"
26
34
  />
27
35
  </div>
36
+ <ScrollArrow
37
+ v-show="showRight"
38
+ side="right"
39
+ @start="startScroll(1)"
40
+ @end="stopScroll"
41
+ />
28
42
  </div>
29
43
  </template>
30
44
 
@@ -32,16 +46,32 @@
32
46
  import { computed, useBlokkli, useTemplateRef, onBeforeUnmount } from "#imports";
33
47
  import Interactions from "./Interactions/index.vue";
34
48
  import Title from "./Title/index.vue";
35
- import { useStickyToolbar } from "#blokkli/editor/composables";
49
+ import ScrollArrow from "./ScrollArrow/index.vue";
50
+ import { onBlokkliEvent, useStickyToolbar } from "#blokkli/editor/composables";
51
+ import { useToolbarScroll } from "./useToolbarScroll";
36
52
  const { selection, ui } = useBlokkli();
37
53
  const ACTIONS_HEIGHT = 52;
38
54
  const el = useTemplateRef("el");
55
+ const contentEl = useTemplateRef("contentEl");
56
+ const {
57
+ scrollX,
58
+ showLeft,
59
+ showRight,
60
+ startScroll,
61
+ stopScroll,
62
+ scrollIntoView
63
+ } = useToolbarScroll({
64
+ viewportEl: el,
65
+ contentEl
66
+ });
67
+ onBlokkliEvent("actions:scrollIntoView", (e) => {
68
+ scrollIntoView(e.element);
69
+ });
39
70
  useStickyToolbar(el, {
40
71
  getPlacementY: () => "top",
41
72
  shouldUpdate: () => !ui.actionsToolbarLocked.value && isVisible.value,
42
73
  getHeight: () => ACTIONS_HEIGHT,
43
- getMargin: () => 30,
44
- allowHorizontalOverflow: true
74
+ getMargin: () => 30
45
75
  });
46
76
  let mouseLeaveTimeout = null;
47
77
  function onMouseLeave() {
@@ -67,6 +97,9 @@ onBeforeUnmount(() => {
67
97
  const hasAnythingSelected = computed(
68
98
  () => selection.hasHostSelected.value || !!selection.items.value.length
69
99
  );
100
+ const paddedViewportWidth = computed(
101
+ () => Math.max(120, Math.round(ui.visibleViewportPadded.value.width))
102
+ );
70
103
  const isVisible = computed(() => {
71
104
  return !selection.isDragging.value && !selection.activeFieldLabel.value && !ui.isAnimating.value && !ui.hasTransformOverlayOpen.value && hasAnythingSelected.value && !ui.hasTooltipOpen.value && !ui.isApproving.value;
72
105
  });
@@ -80,7 +113,6 @@ export default {
80
113
 
81
114
  <style>/*! tailwindcss v4.2.4 | MIT License | https://tailwindcss.com */
82
115
  .bk.bk-blokkli-item-actions-inner {
83
- transform: translate3d(0, 0, 0);
84
116
  backface-visibility: hidden;
85
117
  bottom: var(--bk-root-offset-bottom);
86
118
  }
@@ -89,6 +121,14 @@ export default {
89
121
  top: 0px !important;
90
122
  width: auto !important;
91
123
  bottom: initial !important;
124
+ max-width: var(--bk-actions-max-width, calc(100vw - 60px));
125
+ clip-path: inset(-100vh 0 -100vh 0);
126
+ }
127
+ }
128
+ @media (width >= 64rem) {
129
+ .bk .bk-blokkli-item-actions-controls {
130
+ transform: translate3d(var(--bk-actions-scroll-x, 0px), 0, 0);
131
+ will-change: transform;
92
132
  }
93
133
  }
94
134
  .bk-is-locked:is(.bk .bk-blokkli-item-actions-controls) {
@@ -0,0 +1,25 @@
1
+ import type { Ref } from 'vue';
2
+ export type UseToolbarScrollOptions = {
3
+ viewportEl: Readonly<Ref<HTMLElement | null>>;
4
+ contentEl: Readonly<Ref<HTMLElement | null>>;
5
+ };
6
+ /**
7
+ * Drives horizontal scroll of the actions toolbar's inner content via a
8
+ * transform translate, exposing arrow visibility flags and press-and-hold
9
+ * scroll controls.
10
+ *
11
+ * The viewport caps at the editor's safe area on desktop; when the content
12
+ * (icons, options, action buttons) is wider, the user scrolls by pressing
13
+ * and holding the arrow buttons rendered on the viewport edges. The
14
+ * underlying transform is applied without a CSS transition so selection
15
+ * changes don't animate back to zero. Mobile is unaffected — the options
16
+ * strip keeps its own native horizontal overflow there.
17
+ */
18
+ export declare function useToolbarScroll(options: UseToolbarScrollOptions): {
19
+ scrollX: any;
20
+ showLeft: any;
21
+ showRight: any;
22
+ startScroll: (direction: -1 | 1) => void;
23
+ stopScroll: () => void;
24
+ scrollIntoView: (element: HTMLElement) => void;
25
+ };
@@ -0,0 +1,125 @@
1
+ import { ref, computed, onBeforeUnmount } from "#imports";
2
+ import { onElementResize } from "#blokkli/editor/composables";
3
+ const LG_MEDIA_QUERY = "(min-width: 1024px)";
4
+ const SCROLL_SPEED_PX_PER_SEC = 1400;
5
+ const ARROW_OVERLAP_PX = 60;
6
+ export function useToolbarScroll(options) {
7
+ const scrollX = ref(0);
8
+ const viewportWidth = ref(0);
9
+ const contentWidth = ref(0);
10
+ const isLg = ref(
11
+ typeof window !== "undefined" ? window.matchMedia(LG_MEDIA_QUERY).matches : false
12
+ );
13
+ const maxScroll = computed(() => {
14
+ if (!isLg.value) {
15
+ return 0;
16
+ }
17
+ return Math.max(0, contentWidth.value - viewportWidth.value);
18
+ });
19
+ const showLeft = computed(() => maxScroll.value > 0 && scrollX.value > 0);
20
+ const showRight = computed(
21
+ () => maxScroll.value > 0 && scrollX.value < maxScroll.value
22
+ );
23
+ function clamp() {
24
+ if (scrollX.value > maxScroll.value) {
25
+ scrollX.value = maxScroll.value;
26
+ } else if (scrollX.value < 0) {
27
+ scrollX.value = 0;
28
+ }
29
+ }
30
+ let rafId = null;
31
+ let lastTime = null;
32
+ let currentDirection = 0;
33
+ function tick(now) {
34
+ if (lastTime === null) {
35
+ lastTime = now;
36
+ }
37
+ const dt = (now - lastTime) / 1e3;
38
+ lastTime = now;
39
+ const next = Math.max(
40
+ 0,
41
+ Math.min(
42
+ maxScroll.value,
43
+ scrollX.value + currentDirection * SCROLL_SPEED_PX_PER_SEC * dt
44
+ )
45
+ );
46
+ scrollX.value = next;
47
+ if (currentDirection < 0 && next === 0 || currentDirection > 0 && next >= maxScroll.value) {
48
+ stopScroll();
49
+ return;
50
+ }
51
+ rafId = window.requestAnimationFrame(tick);
52
+ }
53
+ function startScroll(direction) {
54
+ if (rafId !== null) {
55
+ return;
56
+ }
57
+ currentDirection = direction;
58
+ lastTime = null;
59
+ rafId = window.requestAnimationFrame(tick);
60
+ }
61
+ function stopScroll() {
62
+ if (rafId !== null) {
63
+ window.cancelAnimationFrame(rafId);
64
+ rafId = null;
65
+ }
66
+ lastTime = null;
67
+ currentDirection = 0;
68
+ }
69
+ function scrollIntoView(element) {
70
+ const viewport = options.viewportEl.value;
71
+ if (!viewport || !isLg.value || maxScroll.value <= 0) {
72
+ return;
73
+ }
74
+ if (!viewport.contains(element)) {
75
+ return;
76
+ }
77
+ const viewportRect = viewport.getBoundingClientRect();
78
+ const elRect = element.getBoundingClientRect();
79
+ const leftOverflow = viewportRect.left + ARROW_OVERLAP_PX - elRect.left;
80
+ const rightOverflow = elRect.right - (viewportRect.right - ARROW_OVERLAP_PX);
81
+ let next = scrollX.value;
82
+ if (leftOverflow > 0) {
83
+ next -= leftOverflow;
84
+ } else if (rightOverflow > 0) {
85
+ next += rightOverflow;
86
+ } else {
87
+ return;
88
+ }
89
+ scrollX.value = Math.max(0, Math.min(maxScroll.value, next));
90
+ }
91
+ onElementResize(options.viewportEl, (size) => {
92
+ viewportWidth.value = size.width;
93
+ clamp();
94
+ });
95
+ onElementResize(options.contentEl, (size) => {
96
+ contentWidth.value = size.width;
97
+ clamp();
98
+ });
99
+ let mql = null;
100
+ function onMediaChange(e) {
101
+ isLg.value = e.matches;
102
+ if (!e.matches) {
103
+ scrollX.value = 0;
104
+ stopScroll();
105
+ } else {
106
+ clamp();
107
+ }
108
+ }
109
+ if (typeof window !== "undefined") {
110
+ mql = window.matchMedia(LG_MEDIA_QUERY);
111
+ mql.addEventListener("change", onMediaChange);
112
+ }
113
+ onBeforeUnmount(() => {
114
+ mql?.removeEventListener("change", onMediaChange);
115
+ stopScroll();
116
+ });
117
+ return {
118
+ scrollX,
119
+ showLeft,
120
+ showRight,
121
+ startScroll,
122
+ stopScroll,
123
+ scrollIntoView
124
+ };
125
+ }
@@ -7,8 +7,6 @@
7
7
  class="bk-add-item"
8
8
  :menu="menu"
9
9
  :data-sortli-id="id"
10
- :data-test="'add-list-item-' + id"
11
- :data-test-disabled="disabled"
12
10
  :class="[
13
11
  {
14
12
  'bk-is-disabled': disabled