@blokkli/editor 2.0.0-alpha.38 → 2.0.0-alpha.39

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 (108) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/module.mjs +2 -1
  3. package/dist/modules/agent/runtime/app/composables/agentProvider.d.ts +1 -0
  4. package/dist/modules/agent/runtime/app/composables/agentProvider.js +51 -7
  5. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewCode/index.d.vue.ts +6 -0
  6. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewCode/index.vue +9 -0
  7. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewCode/index.vue.d.ts +6 -0
  8. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewCsv/index.d.vue.ts +6 -0
  9. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewCsv/index.vue +31 -0
  10. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewCsv/index.vue.d.ts +6 -0
  11. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewHtml/index.d.vue.ts +6 -0
  12. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewHtml/index.vue +12 -0
  13. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewHtml/index.vue.d.ts +6 -0
  14. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewMarkdown/index.d.vue.ts +6 -0
  15. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewMarkdown/index.vue +17 -0
  16. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/PreviewMarkdown/index.vue.d.ts +6 -0
  17. package/dist/modules/agent/runtime/app/features/agent/Panel/Attachment/index.vue +31 -1
  18. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/Item/ServerTool/index.d.vue.ts +1 -1
  19. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/Item/ServerTool/index.vue +9 -7
  20. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/Item/ServerTool/index.vue.d.ts +1 -1
  21. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/Item/Tool/index.d.vue.ts +3 -0
  22. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/Item/Tool/index.vue +31 -7
  23. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/Item/Tool/index.vue.d.ts +3 -0
  24. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/Item/index.d.vue.ts +1 -0
  25. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/Item/index.vue +18 -2
  26. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/Item/index.vue.d.ts +1 -0
  27. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/index.d.vue.ts +1 -0
  28. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/index.vue +5 -2
  29. package/dist/modules/agent/runtime/app/features/agent/Panel/Conversation/index.vue.d.ts +1 -0
  30. package/dist/modules/agent/runtime/app/features/agent/Panel/DebugGallery/index.vue +2 -1
  31. package/dist/modules/agent/runtime/app/features/agent/Panel/DropHandler/index.d.vue.ts +17 -0
  32. package/dist/modules/agent/runtime/app/features/agent/Panel/DropHandler/index.vue +230 -0
  33. package/dist/modules/agent/runtime/app/features/agent/Panel/DropHandler/index.vue.d.ts +17 -0
  34. package/dist/modules/agent/runtime/app/features/agent/Panel/Input/index.d.vue.ts +4 -2
  35. package/dist/modules/agent/runtime/app/features/agent/Panel/Input/index.vue +5 -8
  36. package/dist/modules/agent/runtime/app/features/agent/Panel/Input/index.vue.d.ts +4 -2
  37. package/dist/modules/agent/runtime/app/features/agent/Panel/Plan/index.vue +1 -1
  38. package/dist/modules/agent/runtime/app/features/agent/Panel/index.d.vue.ts +1 -0
  39. package/dist/modules/agent/runtime/app/features/agent/Panel/index.vue +26 -3
  40. package/dist/modules/agent/runtime/app/features/agent/Panel/index.vue.d.ts +1 -0
  41. package/dist/modules/agent/runtime/app/features/agent/Transcript/index.vue +34 -1
  42. package/dist/modules/agent/runtime/app/features/agent/index.vue +2 -0
  43. package/dist/modules/agent/runtime/app/tools/ask_question/Component.vue +8 -2
  44. package/dist/modules/agent/runtime/app/tools/ask_question/index.d.ts +1 -0
  45. package/dist/modules/agent/runtime/app/tools/ask_question/index.js +9 -1
  46. package/dist/modules/agent/runtime/app/tools/check_readability/index.js +15 -16
  47. package/dist/modules/agent/runtime/app/tools/{analyze_content → get_readability_issues}/index.js +3 -2
  48. package/dist/modules/agent/runtime/app/tools/{batch_rewrite_text → update_text_fields}/Component.d.vue.ts +9 -0
  49. package/dist/modules/agent/runtime/app/tools/{batch_rewrite_text → update_text_fields}/Component.vue +80 -34
  50. package/dist/modules/agent/runtime/app/tools/{batch_rewrite_text → update_text_fields}/Component.vue.d.ts +9 -0
  51. package/dist/modules/agent/runtime/app/tools/update_text_fields/Details/index.d.vue.ts +6 -0
  52. package/dist/modules/agent/runtime/app/tools/update_text_fields/Details/index.vue +24 -0
  53. package/dist/modules/agent/runtime/app/tools/update_text_fields/Details/index.vue.d.ts +6 -0
  54. package/dist/modules/agent/runtime/app/tools/{batch_rewrite_text → update_text_fields}/Item.d.vue.ts +2 -0
  55. package/dist/modules/agent/runtime/app/tools/{batch_rewrite_text → update_text_fields}/Item.vue +9 -4
  56. package/dist/modules/agent/runtime/app/tools/{batch_rewrite_text → update_text_fields}/Item.vue.d.ts +2 -0
  57. package/dist/modules/agent/runtime/app/tools/update_text_fields/index.js +78 -0
  58. package/dist/modules/agent/runtime/app/types/index.d.ts +29 -2
  59. package/dist/modules/agent/runtime/app/types/index.js +3 -2
  60. package/dist/modules/agent/runtime/server/Session.d.ts +5 -1
  61. package/dist/modules/agent/runtime/server/Session.js +34 -6
  62. package/dist/modules/agent/runtime/server/default-skills/adding-new-paragraphs.js +1 -1
  63. package/dist/modules/agent/runtime/server/default-skills/fixReadability.js +3 -2
  64. package/dist/modules/agent/runtime/server/default-skills/pageReview.js +1 -1
  65. package/dist/modules/agent/runtime/server/default-skills/rewriteAndTranslate.js +2 -3
  66. package/dist/modules/agent/runtime/server/default-system-prompts/available-skills.js +1 -1
  67. package/dist/modules/agent/runtime/server/default-system-prompts/important-rules.js +1 -2
  68. package/dist/modules/agent/runtime/server/default-system-prompts/introduction.js +2 -1
  69. package/dist/modules/agent/runtime/server/default-system-prompts/page-context.js +1 -1
  70. package/dist/modules/agent/runtime/server/default-system-prompts/workflow.js +1 -1
  71. package/dist/modules/agent/runtime/server/helpers.js +2 -1
  72. package/dist/modules/agent/runtime/server/providers/anthropic.js +7 -4
  73. package/dist/modules/agent/runtime/server/providers/openai.js +167 -12
  74. package/dist/modules/agent/runtime/server/providers/types.d.ts +7 -2
  75. package/dist/modules/agent/runtime/server/server-tools/complete_plan_step/index.js +15 -0
  76. package/dist/modules/agent/runtime/server/server-tools/index.d.ts +6 -0
  77. package/dist/modules/agent/runtime/server/server-tools/{load_skill → load_skills}/index.d.ts +2 -2
  78. package/dist/modules/agent/runtime/server/server-tools/load_skills/index.js +80 -0
  79. package/dist/modules/agent/runtime/server/server-tools/load_tools/index.js +1 -0
  80. package/dist/modules/agent/runtime/server/skills/types.d.ts +4 -0
  81. package/dist/modules/agent/runtime/shared/types.d.ts +20 -2
  82. package/dist/modules/agent/runtime/shared/types.js +6 -0
  83. package/dist/modules/charts/runtime/blokkli/skills/charts.js +12 -3
  84. package/dist/runtime/editor/components/DiffViewer/DiffDisplay/index.d.vue.ts +9 -0
  85. package/dist/runtime/editor/components/DiffViewer/DiffDisplay/index.vue +31 -0
  86. package/dist/runtime/editor/components/DiffViewer/DiffDisplay/index.vue.d.ts +9 -0
  87. package/dist/runtime/editor/components/DiffViewer/DiffValue.vue +7 -4
  88. package/dist/runtime/editor/components/DiffViewer/State.vue +8 -30
  89. package/dist/runtime/editor/components/FlexTextarea/index.d.vue.ts +1 -0
  90. package/dist/runtime/editor/components/FlexTextarea/index.vue +1 -1
  91. package/dist/runtime/editor/components/FlexTextarea/index.vue.d.ts +1 -0
  92. package/dist/runtime/editor/components/index.d.ts +2 -1
  93. package/dist/runtime/editor/components/index.js +2 -0
  94. package/dist/runtime/editor/css/output.css +1 -1
  95. package/dist/runtime/editor/features/analyze/index.vue +1 -1
  96. package/dist/runtime/editor/features/edit/index.vue +20 -0
  97. package/dist/runtime/editor/providers/definition.d.ts +2 -1
  98. package/dist/runtime/editor/providers/definition.js +5 -1
  99. package/dist/runtime/editor/providers/storage.js +1 -1
  100. package/dist/runtime/editor/translations/de.json +4 -0
  101. package/dist/runtime/editor/translations/fr.json +4 -0
  102. package/dist/runtime/editor/translations/gsw_CH.json +4 -0
  103. package/dist/runtime/editor/translations/it.json +4 -0
  104. package/package.json +3 -2
  105. package/dist/modules/agent/runtime/app/tools/batch_rewrite_text/index.js +0 -55
  106. package/dist/modules/agent/runtime/server/server-tools/load_skill/index.js +0 -58
  107. /package/dist/modules/agent/runtime/app/tools/{analyze_content → get_readability_issues}/index.d.ts +0 -0
  108. /package/dist/modules/agent/runtime/app/tools/{batch_rewrite_text → update_text_fields}/index.d.ts +0 -0
@@ -1,13 +1,14 @@
1
1
  import { z } from "zod";
2
2
  import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
- const nodeSchema = z.object({
4
- description: z.string().optional(),
5
- impact: z.string().optional(),
6
- scores: z.record(z.string(), z.number()).optional()
7
- });
3
+ function impactToLevel(impact) {
4
+ if (impact === "critical" || impact === "serious") return "hard";
5
+ if (impact === "moderate") return "ok";
6
+ return "good";
7
+ }
8
8
  const textResultSchema = z.object({
9
9
  text: z.string(),
10
- nodes: z.array(nodeSchema)
10
+ level: z.enum(["good", "ok", "hard"]),
11
+ scores: z.record(z.string(), z.number())
11
12
  });
12
13
  const paramsSchema = z.object({
13
14
  texts: z.array(z.string()).describe(
@@ -19,7 +20,7 @@ const resultSchema = z.object({
19
20
  });
20
21
  export default defineBlokkliAgentTool({
21
22
  name: "check_readability_for_texts",
22
- description: "Check readability scores for one or more text strings. Returns readability metrics (LIX, CLI, ARI) for each text. Use this to evaluate whether a rewritten text has better readability before applying it.",
23
+ description: 'Check readability scores for one or more text strings. Returns a readability level ("good", "ok", or "hard") and metrics (LIX, CLI, ARI) for each text. Use this to evaluate whether a rewritten text has better readability before applying it.',
23
24
  category: "query",
24
25
  lazy: true,
25
26
  modes: ["readonly", "editing", "translating", "review"],
@@ -36,16 +37,14 @@ export default defineBlokkliAgentTool({
36
37
  const { analyze, $t } = ctx.app;
37
38
  await analyze.ensureInitialized();
38
39
  const rawResults = await analyze.runOnTexts(params.texts, "readability");
39
- const results = rawResults.map(
40
- (tr) => ({
40
+ const results = rawResults.map((tr) => {
41
+ const node = tr.nodes[0];
42
+ return {
41
43
  text: tr.text,
42
- nodes: tr.nodes.map((node) => ({
43
- description: node.description,
44
- impact: node.impact,
45
- scores: node.scores
46
- }))
47
- })
48
- );
44
+ level: impactToLevel(node?.impact),
45
+ scores: node?.scores ?? {}
46
+ };
47
+ });
49
48
  return {
50
49
  label: $t(
51
50
  "aiAgentCheckReadabilityDone",
@@ -20,12 +20,13 @@ function resolveTargetInfo(target) {
20
20
  let fieldName;
21
21
  let fieldEl;
22
22
  let el = target;
23
- while (el && el !== blockEl) {
23
+ while (el) {
24
24
  if (el.dataset.blokkliEditableField) {
25
25
  fieldName = el.dataset.blokkliEditableField;
26
26
  fieldEl = el;
27
27
  break;
28
28
  }
29
+ if (el === blockEl) break;
29
30
  el = el.parentElement;
30
31
  }
31
32
  const fieldText = fieldEl?.textContent?.trim() || void 0;
@@ -33,7 +34,7 @@ function resolveTargetInfo(target) {
33
34
  }
34
35
  export default defineBlokkliAgentTool({
35
36
  name: "get_readability_issues",
36
- description: "Run all readability analyzers against the full page. Returns an object keyed by paragraph UUID and field name, with the current field value and a list of issues. Each issue contains the flagged text segment, impact, and scores. Use the result to call batch_rewrite_text directly.",
37
+ description: "Run all readability analyzers against the full page. Returns an object keyed by paragraph UUID and field name, with the current field value and a list of issues. Each issue contains the flagged text segment, impact, and scores. Use the result to call update_text_fields directly.",
37
38
  category: "query",
38
39
  volatile: true,
39
40
  lazy: true,
@@ -4,6 +4,11 @@ type __VLS_Props = {
4
4
  context: McpToolContext;
5
5
  params: BatchRewriteParams;
6
6
  };
7
+ export type BatchRewriteDetailItem = {
8
+ fieldLabel: string;
9
+ before: string;
10
+ after: string;
11
+ };
7
12
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
8
13
  done: (result: {
9
14
  acceptedCount: number;
@@ -13,6 +18,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
13
18
  label: string;
14
19
  agentMessage?: string | undefined;
15
20
  historyIndex?: number | undefined;
21
+ } & {
22
+ _details?: BatchRewriteDetailItem[];
16
23
  }) => any;
17
24
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
18
25
  onDone?: ((result: {
@@ -23,6 +30,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
23
30
  label: string;
24
31
  agentMessage?: string | undefined;
25
32
  historyIndex?: number | undefined;
33
+ } & {
34
+ _details?: BatchRewriteDetailItem[];
26
35
  }) => any) | undefined;
27
36
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
28
37
  declare const _default: typeof __VLS_export;
@@ -10,21 +10,28 @@
10
10
  "
11
11
  @cancel="rejectAll"
12
12
  >
13
- <div
14
- v-if="!isApplying"
15
- class="bk-batch-rewrite-list"
16
- @mouseleave="onMouseLeave"
17
- >
18
- <ItemComponent
19
- v-for="item in items"
20
- :key="item.id"
21
- v-model:selected="selected[item.id]"
22
- v-model:reason="reasons[item.id]"
23
- :uuid="item.uuid"
24
- :field-name="item.fieldName"
25
- :field-label="item.fieldLabel"
26
- :new-value="item.value"
27
- />
13
+ <div v-if="!isApplying">
14
+ <div class="bk-batch-rewrite-mode-selector">
15
+ <FormRadioTabs
16
+ :id="'batch-rewrite-diff-mode-' + id"
17
+ v-model="diffMode"
18
+ :options="diffModeOptions"
19
+ :label="$t('diffModeLabel', 'Display')"
20
+ />
21
+ </div>
22
+ <div class="bk-batch-rewrite-list" @mouseleave="onMouseLeave">
23
+ <ItemComponent
24
+ v-for="item in items"
25
+ :key="item.id"
26
+ v-model:selected="selected[item.id]"
27
+ v-model:reason="reasons[item.id]"
28
+ :uuid="item.uuid"
29
+ :field-name="item.fieldName"
30
+ :field-label="item.fieldLabel"
31
+ :new-value="item.value"
32
+ :diff-mode="diffMode"
33
+ />
34
+ </div>
28
35
  </div>
29
36
 
30
37
  <template #actions>
@@ -40,8 +47,8 @@
40
47
  </template>
41
48
 
42
49
  <script setup>
43
- import { computed, useBlokkli, ref, reactive, onMounted } from "#imports";
44
- import { Icon } from "#blokkli/editor/components";
50
+ import { computed, useBlokkli, ref, reactive, onMounted, useId } from "#imports";
51
+ import { Icon, FormRadioTabs } from "#blokkli/editor/components";
45
52
  import ToolCard from "../../features/agent/Panel/ToolCard/index.vue";
46
53
  import ItemComponent from "./Item.vue";
47
54
  import { itemEntityType } from "#blokkli-build/config";
@@ -56,36 +63,63 @@ const {
56
63
  blocks,
57
64
  context: editorContext,
58
65
  types,
59
- eventBus
66
+ directive,
67
+ eventBus,
68
+ storage
60
69
  } = useBlokkli();
70
+ const id = useId();
71
+ const diffMode = storage.use("diffMode", "inline");
72
+ const diffModeOptions = computed(() => [
73
+ { value: "inline", label: $t("diffModeInline", "Inline") },
74
+ { value: "side_by_side", label: $t("diffModeSideBySide", "Both") },
75
+ { value: "after", label: $t("diffModeAfter", "After") }
76
+ ]);
61
77
  const isApplying = ref(false);
62
78
  onMounted(() => {
63
79
  if (props.params.requireApproval === false) {
64
80
  applySelected();
65
81
  }
66
82
  });
67
- function resolveFieldLabel(uuid, fieldName) {
68
- let entityType;
69
- let bundle;
83
+ function resolveHost(uuid) {
70
84
  if (uuid === editorContext.value.entityUuid) {
71
- entityType = editorContext.value.entityType;
72
- bundle = editorContext.value.entityBundle;
73
- } else {
74
- const block = blocks.getBlock(uuid);
75
- if (!block) {
76
- return fieldName;
77
- }
78
- entityType = itemEntityType;
79
- bundle = block.bundle;
85
+ return {
86
+ entityType: editorContext.value.entityType,
87
+ bundle: editorContext.value.entityBundle
88
+ };
80
89
  }
90
+ const block = blocks.getBlock(uuid);
91
+ if (!block) return null;
92
+ return { entityType: itemEntityType, bundle: block.bundle };
93
+ }
94
+ function resolveFieldLabel(uuid, fieldName) {
95
+ const host = resolveHost(uuid);
96
+ if (!host) return fieldName;
81
97
  const config = types.editableFieldConfig.forName(
82
- entityType,
83
- bundle,
98
+ host.entityType,
99
+ host.bundle,
84
100
  fieldName
85
101
  );
86
102
  return config?.label || fieldName;
87
103
  }
104
+ function getCurrentValue(uuid, fieldName) {
105
+ const host = resolveHost(uuid);
106
+ if (!host) return null;
107
+ const el = directive.findEditableElement(fieldName, {
108
+ type: host.entityType,
109
+ bundle: host.bundle,
110
+ uuid
111
+ });
112
+ if (!el) return null;
113
+ const cfg = types.editableFieldConfig.forName(
114
+ host.entityType,
115
+ host.bundle,
116
+ fieldName
117
+ );
118
+ if (!cfg || cfg.type === "table") return null;
119
+ return cfg.type === "plain" ? el.textContent || "" : el.innerHTML;
120
+ }
88
121
  let idCounter = 0;
122
+ const beforeValues = /* @__PURE__ */ new Map();
89
123
  const items = Object.entries(props.params.uuids).flatMap(
90
124
  ([uuid, fields]) => Object.entries(fields).map(([fieldName, value]) => ({
91
125
  id: idCounter++,
@@ -94,7 +128,13 @@ const items = Object.entries(props.params.uuids).flatMap(
94
128
  fieldLabel: resolveFieldLabel(uuid, fieldName),
95
129
  value
96
130
  }))
97
- );
131
+ ).filter((item) => {
132
+ const current = getCurrentValue(item.uuid, item.fieldName);
133
+ if (current !== null) {
134
+ beforeValues.set(item.id, current);
135
+ }
136
+ return current === null || current !== item.value;
137
+ });
98
138
  const selected = reactive(
99
139
  Object.fromEntries(items.map((item) => [item.id, true]))
100
140
  );
@@ -162,12 +202,18 @@ async function applySelected() {
162
202
  } else if (rejectedWithoutReason.length > 2) {
163
203
  agentMessage = "Some changes were rejected without a reason. Ask the user what they would like to change instead.";
164
204
  }
205
+ const _details = items.filter((item) => selected[item.id]).map((item) => ({
206
+ fieldLabel: item.fieldLabel,
207
+ before: beforeValues.get(item.id) || "",
208
+ after: item.value
209
+ }));
165
210
  emit("done", {
166
211
  acceptedCount,
167
212
  rejectedByUser,
168
213
  label,
169
214
  agentMessage,
170
- historyIndex: state.currentMutationIndex.value
215
+ historyIndex: state.currentMutationIndex.value,
216
+ _details
171
217
  });
172
218
  }
173
219
  function rejectAll() {
@@ -4,6 +4,11 @@ type __VLS_Props = {
4
4
  context: McpToolContext;
5
5
  params: BatchRewriteParams;
6
6
  };
7
+ export type BatchRewriteDetailItem = {
8
+ fieldLabel: string;
9
+ before: string;
10
+ after: string;
11
+ };
7
12
  declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {} & {
8
13
  done: (result: {
9
14
  acceptedCount: number;
@@ -13,6 +18,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
13
18
  label: string;
14
19
  agentMessage?: string | undefined;
15
20
  historyIndex?: number | undefined;
21
+ } & {
22
+ _details?: BatchRewriteDetailItem[];
16
23
  }) => any;
17
24
  }, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{
18
25
  onDone?: ((result: {
@@ -23,6 +30,8 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
23
30
  label: string;
24
31
  agentMessage?: string | undefined;
25
32
  historyIndex?: number | undefined;
33
+ } & {
34
+ _details?: BatchRewriteDetailItem[];
26
35
  }) => any) | undefined;
27
36
  }>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
28
37
  declare const _default: typeof __VLS_export;
@@ -0,0 +1,6 @@
1
+ type __VLS_Props = {
2
+ details: unknown;
3
+ };
4
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
5
+ declare const _default: typeof __VLS_export;
6
+ export default _default;
@@ -0,0 +1,24 @@
1
+ <template>
2
+ <div class="bk-batch-rewrite-details">
3
+ <div
4
+ v-for="(item, index) in items"
5
+ :key="index"
6
+ class="bk-batch-rewrite-details-item"
7
+ >
8
+ <div class="bk-batch-rewrite-details-label">{{ item.fieldLabel }}</div>
9
+ <DiffDisplay :before="item.before" :after="item.after" mode="inline" />
10
+ </div>
11
+ </div>
12
+ </template>
13
+
14
+ <script setup>
15
+ import { computed } from "#imports";
16
+ import { DiffDisplay } from "#blokkli/editor/components";
17
+ const props = defineProps({
18
+ details: { type: null, required: true }
19
+ });
20
+ const items = computed(() => {
21
+ if (!Array.isArray(props.details)) return [];
22
+ return props.details;
23
+ });
24
+ </script>
@@ -0,0 +1,6 @@
1
+ type __VLS_Props = {
2
+ details: unknown;
3
+ };
4
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
5
+ declare const _default: typeof __VLS_export;
6
+ export default _default;
@@ -1,8 +1,10 @@
1
+ import type { DiffDisplayMode } from '#blokkli/editor/components/DiffViewer/DiffDisplay/index.vue';
1
2
  type __VLS_Props = {
2
3
  uuid: string;
3
4
  fieldName: string;
4
5
  fieldLabel: string;
5
6
  newValue: string;
7
+ diffMode: DiffDisplayMode;
6
8
  };
7
9
  type __VLS_ModelProps = {
8
10
  'selected'?: boolean;
@@ -9,8 +9,12 @@
9
9
  <span>{{ fieldLabel }}</span>
10
10
  </label>
11
11
  <div class="bk-batch-rewrite-change">
12
- <div @click.prevent="onChange">
13
- <DiffValue :before="override.originalValue" :after="newValue" />
12
+ <div>
13
+ <DiffDisplay
14
+ :before="override.originalValue"
15
+ :after="newValue"
16
+ :mode="diffMode"
17
+ />
14
18
  </div>
15
19
  <div v-if="!selected" class="bk-batch-rewrite-reason">
16
20
  <FlexTextarea
@@ -33,14 +37,15 @@
33
37
 
34
38
  <script setup>
35
39
  import { watch, onBeforeUnmount, useBlokkli, nextTick } from "#imports";
36
- import { DiffValue, FlexTextarea } from "#blokkli/editor/components";
40
+ import { DiffDisplay, FlexTextarea } from "#blokkli/editor/components";
37
41
  import { useEditableFieldOverride } from "#blokkli/editor/composables";
38
42
  import { itemEntityType } from "#blokkli-build/config";
39
43
  const props = defineProps({
40
44
  uuid: { type: String, required: true },
41
45
  fieldName: { type: String, required: true },
42
46
  fieldLabel: { type: String, required: true },
43
- newValue: { type: String, required: true }
47
+ newValue: { type: String, required: true },
48
+ diffMode: { type: String, required: true }
44
49
  });
45
50
  const selected = defineModel("selected", { type: Boolean, ...{ default: false } });
46
51
  const reason = defineModel("reason", { type: String, ...{ default: "" } });
@@ -1,8 +1,10 @@
1
+ import type { DiffDisplayMode } from '#blokkli/editor/components/DiffViewer/DiffDisplay/index.vue';
1
2
  type __VLS_Props = {
2
3
  uuid: string;
3
4
  fieldName: string;
4
5
  fieldLabel: string;
5
6
  newValue: string;
7
+ diffMode: DiffDisplayMode;
6
8
  };
7
9
  type __VLS_ModelProps = {
8
10
  'selected'?: boolean;
@@ -0,0 +1,78 @@
1
+ import { z } from "zod";
2
+ import { defineBlokkliAgentTool } from "#blokkli/agent/app/composables";
3
+ import Component from "./Component.vue";
4
+ import DetailsComponent from "./Details/index.vue";
5
+ const paramsSchema = z.object({
6
+ uuids: z.record(z.string(), z.record(z.string(), z.string())).describe(
7
+ "A map of paragraph uuids containing a map of field names to field values."
8
+ ),
9
+ requireApproval: z.boolean().optional().describe("Whether to show the approval UI.")
10
+ });
11
+ const resultSchema = z.object({
12
+ acceptedCount: z.number().describe("Number of changes accepted by the user"),
13
+ rejectedByUser: z.record(
14
+ z.string(),
15
+ z.record(
16
+ z.string(),
17
+ z.object({
18
+ reasonForRejection: z.string().describe(
19
+ "Reason provided by the user for rejecting, empty if no reason given"
20
+ )
21
+ })
22
+ )
23
+ ).describe(
24
+ "Map of rejected paragraph UUID to field name to rejection details"
25
+ ),
26
+ label: z.string().describe("Human-readable summary shown in the UI"),
27
+ agentMessage: z.string().optional().describe(
28
+ "Detailed message for the agent, replaces label in the LLM context"
29
+ ),
30
+ historyIndex: z.number().optional().describe("The mutation history index after applying changes")
31
+ });
32
+ export default defineBlokkliAgentTool({
33
+ name: "update_text_fields",
34
+ description: 'Update text content fields on one or more paragraphs, identified by UUID. Set requireApproval to true when the user should confirm the changes first. EXAMPLE: { "uuids": { "<UUID>": { "title": "New title", "text": "New text" } } }',
35
+ category: "mutation",
36
+ prunedSummary: (r) => `${r.acceptedCount || 0} accepted, ${Object.keys(r.rejectedByUser || {}).length} rejected`,
37
+ modes: ["editing", "translating"],
38
+ label($t) {
39
+ return $t("aiAgentBatchRewriteTextRunning", "Rewriting multiple texts...");
40
+ },
41
+ paramsSchema,
42
+ resultSchema,
43
+ requiredAdapterMethods: ["updateFieldValueBatched"],
44
+ component: Component,
45
+ detailsComponent: DetailsComponent,
46
+ buildDetails: (result) => result,
47
+ execute(_ctx, params) {
48
+ return params;
49
+ },
50
+ mockParams: () => ({
51
+ uuids: {
52
+ "4526d2d0-f122-4093-902f-e2f00a433981": {
53
+ title: "Seamlessly integrates in any Nuxt setup",
54
+ tagline: "Great Developer Experience"
55
+ },
56
+ "9485812c-0ecd-4699-85b2-3a031d47a0a1": {
57
+ text: "<ul><li>Fully responsive design</li><li>Touch gestures and smooth interactions</li><li>All editing features available on mobile</li><li>Optimized for tablets</li></ul>"
58
+ },
59
+ "67a9e26f-8028-4283-8b7d-8f836355b949": {
60
+ text: "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p><p>Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p><p>Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.</p><p>Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p><p>Curabitur pretium tincidunt lacus. Nulla gravida orci a odio. Nullam varius, turpis et commodo pharetra.</p>"
61
+ },
62
+ "3a2617ed-6844-4d39-859c-82869f4ea5aa": {
63
+ text: "<ul><li>Auto import block components</li><li>Directly define options inside the component</li><li>Support for import chunks</li></ul>"
64
+ }
65
+ },
66
+ requireApproval: true
67
+ }),
68
+ mockParamsVariants: () => [
69
+ {
70
+ uuids: {
71
+ "dev-long-text-block": {
72
+ text: "<h2>The Architecture Behind bl\xF6kkli</h2><p>At its core, bl\xF6kkli is a Nuxt module that injects an editing overlay on top of your existing page. When you enter edit mode, the overlay activates and wraps each block with interactive handles for selection, dragging, and inline editing. The key insight is that your page components render exactly as they would in production \u2014 bl\xF6kkli never replaces them with editor-specific versions. Instead, it reads the DOM to understand the page structure and provides editing affordances on top.</p><p>The provider system is how bl\xF6kkli shares state across the editor. Rather than a single global store, functionality is split into focused providers: one for selection state, one for UI, one for DOM operations, one for animations, and so on. Each provider is injected via Vue provide/inject at the appropriate level \u2014 some are global, some are per-field, some are per-block. This granularity prevents unnecessary reactivity and keeps the editor fast even on complex pages.</p><p>Code generation plays a crucial role in the developer experience. When you run the dev server, bl\xF6kkli scans your block components, extracts their <code>defineBlokkli()</code> calls, and generates TypeScript definitions into the <code>.nuxt/blokkli/</code> directory. These generated types power autocomplete for block bundles, option keys, field names, and adapter methods. The result is that typos and mismatches are caught by your IDE before you even save the file.</p><p>The mutation system deserves special attention. Every change the user makes in the editor is captured as a discrete mutation object with a type, target, and payload. Mutations are queued and sent to the adapter in order. The adapter can batch them, validate them, or reject them. This design makes undo/redo straightforward \u2014 the editor simply replays or reverts mutations. It also makes the AI agent possible, because the agent produces the same mutation objects as manual editing.</p><p>Theming is handled through CSS custom properties defined in JSON theme files. Each theme specifies RGB values for color palettes, and the editor resolves them at runtime. Switching themes is instant because it only updates CSS variables \u2014 no components re-render. The built-in themes (nuxt, fire, gruvbox) demonstrate the range, but creating a custom theme is just a matter of defining your color values in a JSON file and referencing it in your Nuxt config.</p>"
73
+ }
74
+ },
75
+ requireApproval: true
76
+ }
77
+ ]
78
+ });
@@ -189,6 +189,17 @@ export type McpToolDefinition<TParamsSchema extends z.ZodType = z.ZodType, TResu
189
189
  * - Mutation tools (no component): `MutationToolResult`
190
190
  */
191
191
  prunedSummary?: (result: TComponent extends Component ? z.infer<TResultSchema> : TCategory extends 'query' ? z.infer<TResultSchema> : MutationToolResult) => string;
192
+ /**
193
+ * Optional callback that extracts detail data from the tool result.
194
+ * Called after tool execution. The returned value is stored in memory
195
+ * (not persisted) and passed to detailsComponent when expanded.
196
+ */
197
+ buildDetails?: (result: any) => unknown;
198
+ /**
199
+ * Optional Vue component rendered inside the collapsible details area.
200
+ * Receives { details: unknown } as props (the value from buildDetails).
201
+ */
202
+ detailsComponent?: Component;
192
203
  /**
193
204
  * Optional function returning mock params for styling/debugging.
194
205
  * When provided, the debug view will render the component with these params.
@@ -244,6 +255,13 @@ declare const userConversationItemSchema: z.ZodObject<{
244
255
  type: z.ZodLiteral<"text">;
245
256
  id: z.ZodString;
246
257
  content: z.ZodString;
258
+ format: z.ZodEnum<{
259
+ code: "code";
260
+ markdown: "markdown";
261
+ html: "html";
262
+ plaintext: "plaintext";
263
+ csv: "csv";
264
+ }>;
247
265
  }, z.core.$strip>>>;
248
266
  }, z.core.$strip>;
249
267
  /**
@@ -280,7 +298,7 @@ declare const serverToolConversationItemSchema: z.ZodObject<{
280
298
  timestamp: z.ZodNumber;
281
299
  type: z.ZodLiteral<"server_tool">;
282
300
  tool: z.ZodEnum<{
283
- load_skill: "load_skill";
301
+ load_skills: "load_skills";
284
302
  load_tools: "load_tools";
285
303
  create_plan: "create_plan";
286
304
  complete_plan_step: "complete_plan_step";
@@ -310,6 +328,13 @@ export declare const conversationItemSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
310
328
  type: z.ZodLiteral<"text">;
311
329
  id: z.ZodString;
312
330
  content: z.ZodString;
331
+ format: z.ZodEnum<{
332
+ code: "code";
333
+ markdown: "markdown";
334
+ html: "html";
335
+ plaintext: "plaintext";
336
+ csv: "csv";
337
+ }>;
313
338
  }, z.core.$strip>>>;
314
339
  }, z.core.$strip>, z.ZodObject<{
315
340
  id: z.ZodString;
@@ -333,7 +358,7 @@ export declare const conversationItemSchema: z.ZodDiscriminatedUnion<[z.ZodObjec
333
358
  timestamp: z.ZodNumber;
334
359
  type: z.ZodLiteral<"server_tool">;
335
360
  tool: z.ZodEnum<{
336
- load_skill: "load_skill";
361
+ load_skills: "load_skills";
337
362
  load_tools: "load_tools";
338
363
  create_plan: "create_plan";
339
364
  complete_plan_step: "complete_plan_step";
@@ -370,10 +395,12 @@ export type ConversationItem = z.infer<typeof conversationItemSchema> | UnknownC
370
395
  * Only one active item can exist at a time. When complete, it's pushed to conversation history.
371
396
  */
372
397
  export type ActiveItem = AssistantConversationItem | ToolConversationItem;
398
+ export type AttachmentFormat = 'plaintext' | 'markdown' | 'html' | 'csv' | 'code';
373
399
  export type TextAttachment = {
374
400
  type: 'text';
375
401
  id: string;
376
402
  content: string;
403
+ format: AttachmentFormat;
377
404
  };
378
405
  export type Attachment = TextAttachment;
379
406
  export {};
@@ -11,7 +11,8 @@ const userConversationItemSchema = conversationItemBase.extend({
11
11
  z.object({
12
12
  type: z.literal("text"),
13
13
  id: z.string(),
14
- content: z.string()
14
+ content: z.string(),
15
+ format: z.enum(["plaintext", "markdown", "html", "csv", "code"])
15
16
  })
16
17
  ).optional()
17
18
  });
@@ -29,7 +30,7 @@ const toolConversationItemSchema = conversationItemBase.extend({
29
30
  const serverToolConversationItemSchema = conversationItemBase.extend({
30
31
  type: z.literal("server_tool"),
31
32
  tool: z.enum([
32
- "load_skill",
33
+ "load_skills",
33
34
  "load_tools",
34
35
  "create_plan",
35
36
  "complete_plan_step",
@@ -18,12 +18,14 @@ export declare class Session {
18
18
  lazyToolNames: string[];
19
19
  /** Names of lazy tools that have been activated via load_tools */
20
20
  activatedLazyTools: Set<string>;
21
- /** Names of skills that have been loaded via load_skill */
21
+ /** Names of skills that have been loaded via load_skills */
22
22
  loadedSkills: Set<string>;
23
23
  /** Page context received from client on init */
24
24
  pageContext?: PageContext;
25
25
  /** Current plan (null when no plan is active) */
26
26
  plan: ServerPlan | null;
27
+ /** Whether any real work (non-server tool calls) happened since the last plan step started */
28
+ planStepHasWork: boolean;
27
29
  /** Pending plan approval promise resolver */
28
30
  pendingPlanApproval: {
29
31
  resolve: (approved: boolean) => void;
@@ -32,6 +34,8 @@ export declare class Session {
32
34
  private unprunedMessages;
33
35
  /** Last generic tool definitions for transcript */
34
36
  private lastTools;
37
+ /** Last raw request payload for transcript (dev only) */
38
+ private lastDebugPayload;
35
39
  /** Bundled tool metadata map for server-side resolution */
36
40
  private bundledToolMap;
37
41
  /** Cache for resolved JSON Schemas (Zod→JSON Schema is deterministic) */