@blokkli/editor 2.0.0-alpha.61 → 2.0.0-alpha.63
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.
- package/dist/global/types/colorOptions.d.ts +16 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +168 -14
- package/dist/modules/agent/runtime/app/components/Conversation/Item/Assistant/index.vue +14 -5
- package/dist/modules/agent/runtime/app/features/agent/ConversationsAdmin/ConversationsTab/Item.vue +2 -2
- package/dist/modules/agent/runtime/app/features/agent/ConversationsAdmin/RatingsTab/Item.vue +2 -2
- package/dist/modules/agent/runtime/app/features/agent/ConversationsAdmin/SplitView/ConversationDetail.vue +2 -2
- package/dist/modules/agent/runtime/app/features/agent/Transcript/MessageContent.vue +14 -1
- package/dist/modules/agent/runtime/app/features/agent/Transcript/index.vue +30 -12
- package/dist/modules/agent/runtime/app/helpers/linkifyBlockUuids.d.ts +11 -0
- package/dist/modules/agent/runtime/app/helpers/linkifyBlockUuids.js +47 -0
- package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/Component.d.vue.ts +22 -0
- package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/Component.vue +28 -26
- package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/Component.vue.d.ts +22 -0
- package/dist/modules/agent/runtime/app/tools/auto_translate_paragraphs/index.d.ts +15 -0
- package/dist/modules/agent/runtime/app/tools/delegate_text_rewrite/Component.d.vue.ts +22 -0
- package/dist/modules/agent/runtime/app/tools/delegate_text_rewrite/Component.vue +59 -16
- package/dist/modules/agent/runtime/app/tools/delegate_text_rewrite/Component.vue.d.ts +22 -0
- package/dist/modules/agent/runtime/app/tools/delegate_text_rewrite/index.d.ts +15 -0
- package/dist/modules/agent/runtime/app/tools/fieldDiffApproval.d.ts +85 -15
- package/dist/modules/agent/runtime/app/tools/fieldDiffApproval.js +138 -28
- package/dist/modules/agent/runtime/app/tools/schemas.d.ts +15 -5
- package/dist/modules/agent/runtime/app/tools/schemas.js +29 -12
- package/dist/modules/agent/runtime/app/tools/search_text/index.js +1 -1
- package/dist/modules/agent/runtime/app/tools/update_text_fields/Component.d.vue.ts +22 -0
- package/dist/modules/agent/runtime/app/tools/update_text_fields/Component.vue +54 -30
- package/dist/modules/agent/runtime/app/tools/update_text_fields/Component.vue.d.ts +22 -0
- package/dist/modules/agent/runtime/app/tools/update_text_fields/index.d.ts +15 -0
- package/dist/modules/agent/runtime/server/default-system-prompts/architecture.js +1 -1
- package/dist/modules/agent/runtime/server/default-system-prompts/important-rules.js +1 -0
- package/dist/modules/charts/runtime/blokkli/tools/chart_schemas.d.ts +1 -1
- package/dist/modules/charts/runtime/blokkli/tools/chart_schemas.js +12 -5
- package/dist/modules/charts/runtime/components/ChartRenderer/index.vue +7 -16
- package/dist/modules/charts/runtime/features/charts/Editor/ColorDropdown/index.vue +7 -77
- package/dist/modules/charts/runtime/features/charts/Editor/CsvImport/csvHelpers.d.ts +1 -1
- package/dist/modules/charts/runtime/features/charts/Editor/useChartEditorState.d.ts +1 -1
- package/dist/modules/charts/runtime/helpers/index.d.ts +2 -1
- package/dist/modules/charts/runtime/helpers/index.js +4 -2
- package/dist/modules/drupal/graphql/base/fragment.paragraphsBlokkliMutationResult.graphql +3 -0
- package/dist/modules/drupal/runtime/adapter/index.js +38 -27
- package/dist/runtime/composables/useBlokkliRuntimeConfig.d.ts +50 -0
- package/dist/runtime/composables/useBlokkliRuntimeConfig.js +34 -0
- package/dist/runtime/editor/adapter/index.d.ts +2 -1
- package/dist/runtime/editor/components/ColorDropdown/index.d.vue.ts +26 -0
- package/dist/runtime/editor/components/ColorDropdown/index.vue +116 -0
- package/dist/runtime/editor/components/ColorDropdown/index.vue.d.ts +26 -0
- package/dist/runtime/editor/components/DiffApproval/Highlight/Item.d.vue.ts +14 -20
- package/dist/runtime/editor/components/DiffApproval/Highlight/Item.vue +97 -52
- package/dist/runtime/editor/components/DiffApproval/Highlight/Item.vue.d.ts +14 -20
- package/dist/runtime/editor/components/DiffApproval/Highlight/index.d.vue.ts +6 -6
- package/dist/runtime/editor/components/DiffApproval/Highlight/index.vue +30 -21
- package/dist/runtime/editor/components/DiffApproval/Highlight/index.vue.d.ts +6 -6
- package/dist/runtime/editor/components/DiffApproval/Toolbar/index.d.vue.ts +19 -9
- package/dist/runtime/editor/components/DiffApproval/Toolbar/index.vue +18 -9
- package/dist/runtime/editor/components/DiffApproval/Toolbar/index.vue.d.ts +19 -9
- package/dist/runtime/editor/components/DiffApproval/index.d.vue.ts +14 -6
- package/dist/runtime/editor/components/DiffApproval/index.vue +62 -35
- package/dist/runtime/editor/components/DiffApproval/index.vue.d.ts +14 -6
- package/dist/runtime/editor/components/DiffApproval/types.d.ts +32 -0
- package/dist/runtime/editor/components/DiffApproval/types.js +22 -0
- package/dist/runtime/editor/components/Dropdown/index.d.vue.ts +5 -4
- package/dist/runtime/editor/components/Dropdown/index.vue +89 -29
- package/dist/runtime/editor/components/Dropdown/index.vue.d.ts +5 -4
- package/dist/runtime/editor/components/FlexTextarea/index.d.vue.ts +1 -1
- package/dist/runtime/editor/components/FlexTextarea/index.vue.d.ts +1 -1
- package/dist/runtime/editor/components/NestedEditorOverlay/index.d.vue.ts +2 -2
- package/dist/runtime/editor/components/NestedEditorOverlay/index.vue +3 -3
- package/dist/runtime/editor/components/NestedEditorOverlay/index.vue.d.ts +2 -2
- package/dist/runtime/editor/components/PopupHost/index.d.vue.ts +13 -0
- package/dist/runtime/editor/components/PopupHost/index.vue +12 -0
- package/dist/runtime/editor/components/PopupHost/index.vue.d.ts +13 -0
- package/dist/runtime/editor/components/index.d.ts +2 -0
- package/dist/runtime/editor/components/index.js +2 -0
- package/dist/runtime/editor/css/output.css +1 -1
- package/dist/runtime/editor/features/analyze/Main.vue +15 -2
- package/dist/runtime/editor/features/analyze/Results/ResultsItemNodes.vue +4 -1
- package/dist/runtime/editor/features/analyze/Results/ResultsItemNodesTarget.vue +25 -16
- package/dist/runtime/editor/features/analyze/analyzers/defaults/validations.d.ts +10 -0
- package/dist/runtime/editor/features/analyze/analyzers/defaults/validations.js +39 -0
- package/dist/runtime/editor/features/analyze/analyzers/helpers/Context.d.ts +5 -1
- package/dist/runtime/editor/features/analyze/analyzers/helpers/Context.js +5 -0
- package/dist/runtime/editor/features/analyze/index.vue +0 -1
- package/dist/runtime/editor/features/changelog/changelog.json +9 -1
- package/dist/runtime/editor/features/comments/Comment/Meta/index.vue +1 -1
- package/dist/runtime/editor/features/comments/Comment/index.vue +1 -1
- package/dist/runtime/editor/features/publish/Dialog/Violations.d.vue.ts +12 -0
- package/dist/runtime/editor/features/publish/Dialog/Violations.vue +117 -0
- package/dist/runtime/editor/features/publish/Dialog/Violations.vue.d.ts +12 -0
- package/dist/runtime/editor/features/publish/Dialog/index.vue +61 -24
- package/dist/runtime/editor/features/publish/index.vue +2 -4
- package/dist/runtime/editor/features/publish/types.d.ts +0 -4
- package/dist/runtime/editor/helpers/color/index.d.ts +7 -0
- package/dist/runtime/editor/helpers/color/index.js +14 -0
- package/dist/runtime/editor/helpers/diff/index.d.ts +87 -0
- package/dist/runtime/editor/helpers/diff/index.js +256 -0
- package/dist/runtime/editor/helpers/injections.d.ts +11 -0
- package/dist/runtime/editor/helpers/injections.js +1 -0
- package/dist/runtime/editor/plugins/Sidebar/Detached/index.d.vue.ts +1 -1
- package/dist/runtime/editor/plugins/Sidebar/Detached/index.vue.d.ts +1 -1
- package/dist/runtime/editor/plugins/Sidebar/index.d.vue.ts +2 -2
- package/dist/runtime/editor/plugins/Sidebar/index.vue.d.ts +2 -2
- package/dist/runtime/editor/providers/analyze.js +5 -2
- package/dist/runtime/editor/providers/config.d.ts +3 -1
- package/dist/runtime/editor/providers/config.js +46 -15
- package/dist/runtime/editor/providers/state.d.ts +13 -0
- package/dist/runtime/editor/providers/state.js +7 -0
- package/dist/runtime/editor/translations/de.json +7 -4
- package/dist/runtime/editor/translations/fr.json +2 -4
- package/dist/runtime/editor/translations/gsw_CH.json +7 -4
- package/dist/runtime/editor/translations/it.json +2 -4
- package/dist/runtime/helpers/colors.d.ts +39 -0
- package/dist/runtime/helpers/colors.js +28 -0
- package/dist/runtime/types/colors.d.ts +11 -0
- package/package.json +1 -1
- package/dist/runtime/editor/features/validations/Overlay/Item.d.vue.ts +0 -7
- package/dist/runtime/editor/features/validations/Overlay/Item.vue +0 -36
- package/dist/runtime/editor/features/validations/Overlay/Item.vue.d.ts +0 -7
- package/dist/runtime/editor/features/validations/Overlay/index.d.vue.ts +0 -7
- package/dist/runtime/editor/features/validations/Overlay/index.vue +0 -115
- package/dist/runtime/editor/features/validations/Overlay/index.vue.d.ts +0 -7
- package/dist/runtime/editor/features/validations/SidebarItem/index.d.vue.ts +0 -10
- package/dist/runtime/editor/features/validations/SidebarItem/index.vue +0 -41
- package/dist/runtime/editor/features/validations/SidebarItem/index.vue.d.ts +0 -10
- package/dist/runtime/editor/features/validations/index.d.vue.ts +0 -3
- package/dist/runtime/editor/features/validations/index.vue +0 -91
- package/dist/runtime/editor/features/validations/index.vue.d.ts +0 -3
- package/dist/runtime/editor/types/config.d.ts +0 -5
- /package/dist/runtime/{editor/types/config.js → types/colors.js} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { flattenSegments, reassembleValue } from "#blokkli/editor/helpers/diff";
|
|
1
2
|
export function skippedFieldsMessage(skipped) {
|
|
2
3
|
if (!skipped.length) return void 0;
|
|
3
4
|
const list = skipped.map((s) => `"${s.uuid}" ${s.fieldName} (${s.reason})`).join(", ");
|
|
@@ -10,55 +11,164 @@ export function appendAgentNote(message, note) {
|
|
|
10
11
|
|
|
11
12
|
${note}`;
|
|
12
13
|
}
|
|
14
|
+
export function decideFieldUpdates(items, selected, reasons) {
|
|
15
|
+
const rejectedByUser = {};
|
|
16
|
+
const updates = [];
|
|
17
|
+
let acceptedCount = 0;
|
|
18
|
+
let totalCount = 0;
|
|
19
|
+
for (const item of items) {
|
|
20
|
+
if (item.segments) {
|
|
21
|
+
const atoms = flattenSegments(item.segments).filter(
|
|
22
|
+
(s) => s.status !== "matched" || s.beforeHtml !== s.afterHtml
|
|
23
|
+
);
|
|
24
|
+
totalCount += atoms.length;
|
|
25
|
+
const acceptedById = {};
|
|
26
|
+
const rejectedSegments = [];
|
|
27
|
+
let accepted = 0;
|
|
28
|
+
for (const atom of atoms) {
|
|
29
|
+
const key = `${item.id}:${atom.id}`;
|
|
30
|
+
const isAccepted = selected[key] !== false;
|
|
31
|
+
acceptedById[atom.id] = isAccepted;
|
|
32
|
+
if (isAccepted) {
|
|
33
|
+
accepted++;
|
|
34
|
+
} else {
|
|
35
|
+
rejectedSegments.push({
|
|
36
|
+
tag: atom.tag,
|
|
37
|
+
beforeHtml: atom.beforeHtml,
|
|
38
|
+
afterHtml: atom.afterHtml,
|
|
39
|
+
status: atom.status,
|
|
40
|
+
reasonForRejection: reasons[key] || ""
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
acceptedCount += accepted;
|
|
45
|
+
if (accepted > 0) {
|
|
46
|
+
updates.push({
|
|
47
|
+
itemId: item.id,
|
|
48
|
+
uuid: item.uuid,
|
|
49
|
+
fieldName: item.fieldName,
|
|
50
|
+
fieldValue: reassembleValue(item.segments, acceptedById)
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
if (rejectedSegments.length > 0) {
|
|
54
|
+
const fields = rejectedByUser[item.uuid] ?? {};
|
|
55
|
+
fields[item.fieldName] = {
|
|
56
|
+
reasonForRejection: "",
|
|
57
|
+
partial: {
|
|
58
|
+
accepted,
|
|
59
|
+
total: atoms.length,
|
|
60
|
+
rejectedSegments
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
rejectedByUser[item.uuid] = fields;
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
totalCount++;
|
|
67
|
+
const key = String(item.id);
|
|
68
|
+
const isAccepted = selected[key] !== false;
|
|
69
|
+
if (isAccepted) {
|
|
70
|
+
acceptedCount++;
|
|
71
|
+
updates.push({
|
|
72
|
+
itemId: item.id,
|
|
73
|
+
uuid: item.uuid,
|
|
74
|
+
fieldName: item.fieldName,
|
|
75
|
+
fieldValue: item.value
|
|
76
|
+
});
|
|
77
|
+
} else {
|
|
78
|
+
const fields = rejectedByUser[item.uuid] ?? {};
|
|
79
|
+
fields[item.fieldName] = {
|
|
80
|
+
reasonForRejection: reasons[key] || ""
|
|
81
|
+
};
|
|
82
|
+
rejectedByUser[item.uuid] = fields;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return { updates, rejectedByUser, acceptedCount, totalCount };
|
|
87
|
+
}
|
|
13
88
|
export async function applyFieldDiffs(app, adapter, items, selected, reasons) {
|
|
14
89
|
const { $t, state, context } = app;
|
|
15
90
|
const entityUuid = context.value.entityUuid;
|
|
16
|
-
const
|
|
91
|
+
const decision = decideFieldUpdates(items, selected, reasons);
|
|
17
92
|
const batchItems = [];
|
|
18
93
|
const entityItems = [];
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
entityItems.push({ fieldName: item.fieldName, fieldValue: item.value });
|
|
94
|
+
const appliedByItemId = {};
|
|
95
|
+
for (const update of decision.updates) {
|
|
96
|
+
appliedByItemId[update.itemId] = update.fieldValue;
|
|
97
|
+
if (update.uuid === entityUuid) {
|
|
98
|
+
entityItems.push({
|
|
99
|
+
fieldName: update.fieldName,
|
|
100
|
+
fieldValue: update.fieldValue
|
|
101
|
+
});
|
|
28
102
|
} else {
|
|
29
103
|
batchItems.push({
|
|
30
|
-
uuid:
|
|
31
|
-
fieldName:
|
|
32
|
-
fieldValue:
|
|
104
|
+
uuid: update.uuid,
|
|
105
|
+
fieldName: update.fieldName,
|
|
106
|
+
fieldValue: update.fieldValue
|
|
33
107
|
});
|
|
34
108
|
}
|
|
35
109
|
}
|
|
36
110
|
await state.mutateWithLoadingState(
|
|
37
111
|
() => adapter.updateFieldValueBatched({ items: batchItems, entityItems })
|
|
38
112
|
);
|
|
39
|
-
const
|
|
40
|
-
const label = acceptedCount === items.length ? $t(
|
|
113
|
+
const label = decision.acceptedCount === decision.totalCount ? $t(
|
|
41
114
|
"aiAgentBatchRewriteAllApplied",
|
|
42
115
|
"All @count changes applied"
|
|
43
|
-
).replace("@count", String(acceptedCount)) : $t(
|
|
116
|
+
).replace("@count", String(decision.acceptedCount)) : $t(
|
|
44
117
|
"aiAgentBatchRewriteSomeApplied",
|
|
45
118
|
"@applied of @total changes applied"
|
|
46
|
-
).replace("@applied", String(acceptedCount)).replace("@total", String(
|
|
47
|
-
return {
|
|
119
|
+
).replace("@applied", String(decision.acceptedCount)).replace("@total", String(decision.totalCount));
|
|
120
|
+
return {
|
|
121
|
+
...decision,
|
|
122
|
+
label,
|
|
123
|
+
appliedByItemId
|
|
124
|
+
};
|
|
48
125
|
}
|
|
49
|
-
export function
|
|
50
|
-
const
|
|
51
|
-
for (const [uuid, fields] of Object.entries(
|
|
126
|
+
export function partialRejectionGuidance(rejected) {
|
|
127
|
+
const partials = [];
|
|
128
|
+
for (const [uuid, fields] of Object.entries(rejected)) {
|
|
52
129
|
for (const [fieldName, v] of Object.entries(fields)) {
|
|
53
|
-
if (
|
|
130
|
+
if (v.partial && v.partial.accepted > 0) {
|
|
131
|
+
partials.push({ uuid, fieldName });
|
|
132
|
+
}
|
|
54
133
|
}
|
|
55
134
|
}
|
|
56
|
-
if (
|
|
57
|
-
|
|
58
|
-
|
|
135
|
+
if (partials.length === 0) return void 0;
|
|
136
|
+
const fieldList = partials.map((p) => `"${p.fieldName}" (paragraph ${p.uuid})`).join(", ");
|
|
137
|
+
const noun = partials.length === 1 ? "This field was" : "These fields were";
|
|
138
|
+
return `${noun} updated with a hybrid value \u2014 accepted chunks plus the original content of the rejected ones: ${fieldList}. If you follow up on the rejected chunks, scope your change to those chunks only \u2014 use update_text_fields patch mode (operations) with search matching the rejected chunk's original content. Do NOT re-rewrite the whole field; the accepted chunks must stay byte-for-byte identical.`;
|
|
139
|
+
}
|
|
140
|
+
export function rejectedWithoutReasonMessage(rejected) {
|
|
141
|
+
const entries = [];
|
|
142
|
+
for (const [uuid, fields] of Object.entries(rejected)) {
|
|
143
|
+
for (const [fieldName, v] of Object.entries(fields)) {
|
|
144
|
+
if (v.partial) {
|
|
145
|
+
for (const seg of v.partial.rejectedSegments) {
|
|
146
|
+
if (!seg.reasonForRejection) {
|
|
147
|
+
entries.push({
|
|
148
|
+
kind: "segment",
|
|
149
|
+
uuid,
|
|
150
|
+
fieldName,
|
|
151
|
+
tag: seg.tag,
|
|
152
|
+
status: seg.status
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
} else if (!v.reasonForRejection) {
|
|
157
|
+
entries.push({ kind: "field", uuid, fieldName });
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (entries.length === 0) return void 0;
|
|
162
|
+
const describe = (e) => e.kind === "segment" ? `a <${e.tag}> ${e.status === "matched" ? "change" : e.status === "inserted" ? "insertion" : "deletion"} in "${e.fieldName}" of paragraph ${e.uuid}` : `"${e.fieldName}" of paragraph ${e.uuid}`;
|
|
163
|
+
if (entries.length === 1) {
|
|
164
|
+
const it = entries[0];
|
|
165
|
+
if (it.kind === "segment") {
|
|
166
|
+
return `The user rejected ${describe(it)} without a reason. Use the ask_question tool to present 2 or more alternative wordings for that specific chunk \u2014 do not rewrite the whole field.`;
|
|
167
|
+
}
|
|
168
|
+
return `The user rejected ${describe(it)} without a reason. Use the ask_question tool to present the user with 2 or more alternative texts.`;
|
|
59
169
|
}
|
|
60
|
-
if (
|
|
61
|
-
return
|
|
170
|
+
if (entries.length === 2) {
|
|
171
|
+
return `The user rejected ${describe(entries[0])} and ${describe(entries[1])} without a reason. Use the ask_question tool to present 2 or more alternative texts for each.`;
|
|
62
172
|
}
|
|
63
|
-
return
|
|
173
|
+
return "Some changes were rejected without a reason. Ask the user what they would like to change instead.";
|
|
64
174
|
}
|
|
@@ -86,15 +86,25 @@ export declare const optionValueSchema: z.ZodUnion<readonly [z.ZodString, z.ZodB
|
|
|
86
86
|
* - `"before:<UUID>"` — insert before the block with the given UUID
|
|
87
87
|
*/
|
|
88
88
|
export declare const positionSchema: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
89
|
-
/**
|
|
90
|
-
* Shared result schema for the interactive field-diff rewrite tools
|
|
91
|
-
* (`update_text_fields`, `delegate_text_rewrite`). Both present a diff approval
|
|
92
|
-
* UI and report what the user accepted/rejected.
|
|
93
|
-
*/
|
|
94
89
|
export declare const fieldDiffResultSchema: z.ZodObject<{
|
|
95
90
|
acceptedCount: z.ZodNumber;
|
|
96
91
|
rejectedByUser: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
97
92
|
reasonForRejection: z.ZodString;
|
|
93
|
+
partial: z.ZodOptional<z.ZodObject<{
|
|
94
|
+
accepted: z.ZodNumber;
|
|
95
|
+
total: z.ZodNumber;
|
|
96
|
+
rejectedSegments: z.ZodArray<z.ZodObject<{
|
|
97
|
+
tag: z.ZodString;
|
|
98
|
+
beforeHtml: z.ZodString;
|
|
99
|
+
afterHtml: z.ZodString;
|
|
100
|
+
status: z.ZodEnum<{
|
|
101
|
+
deleted: "deleted";
|
|
102
|
+
matched: "matched";
|
|
103
|
+
inserted: "inserted";
|
|
104
|
+
}>;
|
|
105
|
+
reasonForRejection: z.ZodString;
|
|
106
|
+
}, z.core.$strip>>;
|
|
107
|
+
}, z.core.$strip>>;
|
|
98
108
|
}, z.core.$strip>>>;
|
|
99
109
|
label: z.ZodString;
|
|
100
110
|
agentMessage: z.ZodOptional<z.ZodString>;
|
|
@@ -68,20 +68,37 @@ export const optionValueSchema = z.union([
|
|
|
68
68
|
export const positionSchema = z.string().optional().default("end").describe(
|
|
69
69
|
'Where to place the paragraph(s). "start" = beginning, "end" (default) = append at end, "after:<UUID>" = after a specific paragraph, "before:<UUID>" = before a specific paragraph.'
|
|
70
70
|
);
|
|
71
|
+
const rejectedSegmentSchema = z.object({
|
|
72
|
+
tag: z.string().describe('HTML tag of the rejected chunk (e.g. "p", "li", "h2")'),
|
|
73
|
+
beforeHtml: z.string().describe(
|
|
74
|
+
"The original innerHTML kept in the field (empty for newly inserted chunks that were rejected and dropped)"
|
|
75
|
+
),
|
|
76
|
+
afterHtml: z.string().describe(
|
|
77
|
+
"The innerHTML you proposed for this chunk and the user rejected (empty for deletions that were rejected and restored)"
|
|
78
|
+
),
|
|
79
|
+
status: z.enum(["matched", "inserted", "deleted"]).describe(
|
|
80
|
+
"Whether your proposal modified an existing chunk (matched), added a new one (inserted), or removed one (deleted)"
|
|
81
|
+
),
|
|
82
|
+
reasonForRejection: z.string().describe("Per-chunk rejection reason; empty if none given")
|
|
83
|
+
});
|
|
84
|
+
const fieldRejectionSchema = z.object({
|
|
85
|
+
reasonForRejection: z.string().describe(
|
|
86
|
+
"Field-level rejection reason; empty when no reason given or when rejection is per-chunk (see `partial`)"
|
|
87
|
+
),
|
|
88
|
+
partial: z.object({
|
|
89
|
+
accepted: z.number().describe("Number of changed chunks in this field the user accepted"),
|
|
90
|
+
total: z.number().describe("Total number of changed chunks in this field"),
|
|
91
|
+
rejectedSegments: z.array(rejectedSegmentSchema).describe(
|
|
92
|
+
"Details for each rejected chunk. The field still gets updated with a hybrid value combining the accepted chunks and the original content of the rejected ones."
|
|
93
|
+
)
|
|
94
|
+
}).optional().describe(
|
|
95
|
+
"Present when the user evaluated chunk-by-chunk. When `accepted > 0`, the field was updated with a hybrid value; when `accepted === 0`, every chunk was rejected and the field stayed at its original value."
|
|
96
|
+
)
|
|
97
|
+
});
|
|
71
98
|
export const fieldDiffResultSchema = z.object({
|
|
72
99
|
acceptedCount: z.number().describe("Number of changes accepted by the user"),
|
|
73
|
-
rejectedByUser: z.record(
|
|
74
|
-
|
|
75
|
-
z.record(
|
|
76
|
-
z.string(),
|
|
77
|
-
z.object({
|
|
78
|
-
reasonForRejection: z.string().describe(
|
|
79
|
-
"Reason provided by the user for rejecting, empty if no reason given"
|
|
80
|
-
)
|
|
81
|
-
})
|
|
82
|
-
)
|
|
83
|
-
).describe(
|
|
84
|
-
"Map of rejected paragraph UUID to field name to rejection details"
|
|
100
|
+
rejectedByUser: z.record(z.string(), z.record(z.string(), fieldRejectionSchema)).describe(
|
|
101
|
+
"Map of paragraph UUID \u2192 field name \u2192 rejection details. A field appears here when at least one chunk was rejected (or, for non-chunked fields, when the whole field was rejected)."
|
|
85
102
|
),
|
|
86
103
|
label: z.string().describe("Human-readable summary shown in the UI"),
|
|
87
104
|
agentMessage: z.string().optional().describe(
|
|
@@ -57,7 +57,7 @@ export default defineBlokkliAgentTool({
|
|
|
57
57
|
const getBlockOwnText = (el) => {
|
|
58
58
|
if (!el) return "";
|
|
59
59
|
const clone = el.cloneNode(true);
|
|
60
|
-
const nestedBlocks = clone.querySelectorAll("[data-
|
|
60
|
+
const nestedBlocks = clone.querySelectorAll("[data-bk-uuid]");
|
|
61
61
|
nestedBlocks.forEach((nested) => nested.remove());
|
|
62
62
|
const altTexts = element.queryAll(clone, "img", "searchTextAlt", (img) => {
|
|
63
63
|
if (img instanceof HTMLImageElement) {
|
|
@@ -9,6 +9,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
9
9
|
acceptedCount: number;
|
|
10
10
|
rejectedByUser: Record<string, Record<string, {
|
|
11
11
|
reasonForRejection: string;
|
|
12
|
+
partial?: {
|
|
13
|
+
accepted: number;
|
|
14
|
+
total: number;
|
|
15
|
+
rejectedSegments: {
|
|
16
|
+
tag: string;
|
|
17
|
+
beforeHtml: string;
|
|
18
|
+
afterHtml: string;
|
|
19
|
+
status: "deleted" | "matched" | "inserted";
|
|
20
|
+
reasonForRejection: string;
|
|
21
|
+
}[];
|
|
22
|
+
} | undefined;
|
|
12
23
|
}>>;
|
|
13
24
|
label: string;
|
|
14
25
|
agentMessage?: string | undefined;
|
|
@@ -19,6 +30,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
19
30
|
acceptedCount: number;
|
|
20
31
|
rejectedByUser: Record<string, Record<string, {
|
|
21
32
|
reasonForRejection: string;
|
|
33
|
+
partial?: {
|
|
34
|
+
accepted: number;
|
|
35
|
+
total: number;
|
|
36
|
+
rejectedSegments: {
|
|
37
|
+
tag: string;
|
|
38
|
+
beforeHtml: string;
|
|
39
|
+
afterHtml: string;
|
|
40
|
+
status: "deleted" | "matched" | "inserted";
|
|
41
|
+
reasonForRejection: string;
|
|
42
|
+
}[];
|
|
43
|
+
} | undefined;
|
|
22
44
|
}>>;
|
|
23
45
|
label: string;
|
|
24
46
|
agentMessage?: string | undefined;
|
|
@@ -11,10 +11,12 @@
|
|
|
11
11
|
<script setup>
|
|
12
12
|
import { useBlokkli, ref, onMounted } from "#imports";
|
|
13
13
|
import { DiffApproval } from "#blokkli/editor/components";
|
|
14
|
+
import { splitIntoSegments } from "#blokkli/editor/helpers/diff";
|
|
14
15
|
import { applyOperations, resolveHost as resolveBlockHost } from "../helpers";
|
|
15
16
|
import {
|
|
16
17
|
applyFieldDiffs,
|
|
17
18
|
rejectedWithoutReasonMessage,
|
|
19
|
+
partialRejectionGuidance,
|
|
18
20
|
skippedFieldsMessage,
|
|
19
21
|
appendAgentNote
|
|
20
22
|
} from "../fieldDiffApproval";
|
|
@@ -63,6 +65,17 @@ function resolveFieldLabel(uuid, fieldName) {
|
|
|
63
65
|
);
|
|
64
66
|
return config?.label || fieldName;
|
|
65
67
|
}
|
|
68
|
+
function getFieldType(uuid, fieldName) {
|
|
69
|
+
const host = resolveHost(uuid);
|
|
70
|
+
if (!host) return null;
|
|
71
|
+
const cfg = types.editableFieldConfig.forName(
|
|
72
|
+
host.entityType,
|
|
73
|
+
host.bundle,
|
|
74
|
+
fieldName
|
|
75
|
+
);
|
|
76
|
+
if (!cfg || cfg.type === "table") return null;
|
|
77
|
+
return cfg.type === "plain" ? "plain" : "markup";
|
|
78
|
+
}
|
|
66
79
|
function getCurrentValue(uuid, fieldName) {
|
|
67
80
|
const host = resolveHost(uuid);
|
|
68
81
|
if (!host) return null;
|
|
@@ -72,27 +85,29 @@ function getCurrentValue(uuid, fieldName) {
|
|
|
72
85
|
uuid
|
|
73
86
|
});
|
|
74
87
|
if (!el) return null;
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
fieldName
|
|
79
|
-
);
|
|
80
|
-
if (!cfg || cfg.type === "table") return null;
|
|
81
|
-
return cfg.type === "plain" ? el.textContent || "" : el.innerHTML;
|
|
88
|
+
const fieldType = getFieldType(uuid, fieldName);
|
|
89
|
+
if (fieldType === null) return null;
|
|
90
|
+
return fieldType === "plain" ? el.textContent || "" : el.innerHTML;
|
|
82
91
|
}
|
|
83
92
|
let idCounter = 0;
|
|
84
93
|
const beforeValues = /* @__PURE__ */ new Map();
|
|
85
94
|
function buildItems() {
|
|
86
95
|
const result = [];
|
|
96
|
+
const pushItem = (uuid, fieldName, value, fieldType) => {
|
|
97
|
+
result.push({
|
|
98
|
+
id: idCounter++,
|
|
99
|
+
uuid,
|
|
100
|
+
fieldName,
|
|
101
|
+
fieldLabel: resolveFieldLabel(uuid, fieldName),
|
|
102
|
+
value,
|
|
103
|
+
fieldType
|
|
104
|
+
});
|
|
105
|
+
};
|
|
87
106
|
if (props.params.updates) {
|
|
88
107
|
for (const { uuid, fieldName, value } of props.params.updates) {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
fieldName,
|
|
93
|
-
fieldLabel: resolveFieldLabel(uuid, fieldName),
|
|
94
|
-
value
|
|
95
|
-
});
|
|
108
|
+
const fieldType = getFieldType(uuid, fieldName);
|
|
109
|
+
if (fieldType === null) continue;
|
|
110
|
+
pushItem(uuid, fieldName, value, fieldType);
|
|
96
111
|
}
|
|
97
112
|
}
|
|
98
113
|
if (props.params.operations?.length) {
|
|
@@ -113,46 +128,55 @@ function buildItems() {
|
|
|
113
128
|
for (const { uuid, fieldName, ops } of grouped.values()) {
|
|
114
129
|
const current = getCurrentValue(uuid, fieldName);
|
|
115
130
|
if (current === null) continue;
|
|
131
|
+
const fieldType = getFieldType(uuid, fieldName);
|
|
132
|
+
if (fieldType === null) continue;
|
|
116
133
|
const newValue = applyOperations(current, ops);
|
|
117
134
|
if (newValue === current) continue;
|
|
118
|
-
|
|
119
|
-
id: idCounter++,
|
|
120
|
-
uuid,
|
|
121
|
-
fieldName,
|
|
122
|
-
fieldLabel: resolveFieldLabel(uuid, fieldName),
|
|
123
|
-
value: newValue
|
|
124
|
-
});
|
|
135
|
+
pushItem(uuid, fieldName, newValue, fieldType);
|
|
125
136
|
}
|
|
126
137
|
}
|
|
127
138
|
return result;
|
|
128
139
|
}
|
|
129
|
-
const items =
|
|
130
|
-
|
|
140
|
+
const items = [];
|
|
141
|
+
for (const draft of buildItems()) {
|
|
142
|
+
const current = getCurrentValue(draft.uuid, draft.fieldName);
|
|
131
143
|
if (current !== null) {
|
|
132
|
-
beforeValues.set(
|
|
144
|
+
beforeValues.set(draft.id, current);
|
|
145
|
+
if (current === draft.value) continue;
|
|
133
146
|
}
|
|
134
|
-
|
|
135
|
-
|
|
147
|
+
const segments = current !== null ? splitIntoSegments(current, draft.value, draft.fieldType) ?? void 0 : void 0;
|
|
148
|
+
items.push({
|
|
149
|
+
id: draft.id,
|
|
150
|
+
uuid: draft.uuid,
|
|
151
|
+
fieldName: draft.fieldName,
|
|
152
|
+
fieldLabel: draft.fieldLabel,
|
|
153
|
+
value: draft.value,
|
|
154
|
+
segments
|
|
155
|
+
});
|
|
156
|
+
}
|
|
136
157
|
async function applySelected(data) {
|
|
137
158
|
const { selected, reasons } = data;
|
|
138
159
|
isApplying.value = true;
|
|
139
|
-
const { acceptedCount, rejectedByUser, label } = await applyFieldDiffs(
|
|
160
|
+
const { acceptedCount, rejectedByUser, label, appliedByItemId } = await applyFieldDiffs(
|
|
140
161
|
blokkli,
|
|
141
162
|
props.context.adapter,
|
|
142
163
|
items,
|
|
143
164
|
selected,
|
|
144
165
|
reasons
|
|
145
166
|
);
|
|
146
|
-
const _details = items.filter((item) =>
|
|
167
|
+
const _details = items.filter((item) => appliedByItemId[item.id] !== void 0).map((item) => ({
|
|
147
168
|
fieldLabel: item.fieldLabel,
|
|
148
169
|
before: beforeValues.get(item.id) || "",
|
|
149
|
-
after: item.
|
|
170
|
+
after: appliedByItemId[item.id]
|
|
150
171
|
}));
|
|
151
172
|
emitDone({
|
|
152
173
|
acceptedCount,
|
|
153
174
|
rejectedByUser,
|
|
154
175
|
label,
|
|
155
|
-
agentMessage:
|
|
176
|
+
agentMessage: appendAgentNote(
|
|
177
|
+
partialRejectionGuidance(rejectedByUser),
|
|
178
|
+
rejectedWithoutReasonMessage(rejectedByUser)
|
|
179
|
+
),
|
|
156
180
|
historyIndex: state.currentMutationIndex.value,
|
|
157
181
|
_details
|
|
158
182
|
});
|
|
@@ -9,6 +9,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
9
9
|
acceptedCount: number;
|
|
10
10
|
rejectedByUser: Record<string, Record<string, {
|
|
11
11
|
reasonForRejection: string;
|
|
12
|
+
partial?: {
|
|
13
|
+
accepted: number;
|
|
14
|
+
total: number;
|
|
15
|
+
rejectedSegments: {
|
|
16
|
+
tag: string;
|
|
17
|
+
beforeHtml: string;
|
|
18
|
+
afterHtml: string;
|
|
19
|
+
status: "deleted" | "matched" | "inserted";
|
|
20
|
+
reasonForRejection: string;
|
|
21
|
+
}[];
|
|
22
|
+
} | undefined;
|
|
12
23
|
}>>;
|
|
13
24
|
label: string;
|
|
14
25
|
agentMessage?: string | undefined;
|
|
@@ -19,6 +30,17 @@ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {
|
|
|
19
30
|
acceptedCount: number;
|
|
20
31
|
rejectedByUser: Record<string, Record<string, {
|
|
21
32
|
reasonForRejection: string;
|
|
33
|
+
partial?: {
|
|
34
|
+
accepted: number;
|
|
35
|
+
total: number;
|
|
36
|
+
rejectedSegments: {
|
|
37
|
+
tag: string;
|
|
38
|
+
beforeHtml: string;
|
|
39
|
+
afterHtml: string;
|
|
40
|
+
status: "deleted" | "matched" | "inserted";
|
|
41
|
+
reasonForRejection: string;
|
|
42
|
+
}[];
|
|
43
|
+
} | undefined;
|
|
22
44
|
}>>;
|
|
23
45
|
label: string;
|
|
24
46
|
agentMessage?: string | undefined;
|
|
@@ -46,6 +46,21 @@ export declare const resultSchema: z.ZodObject<{
|
|
|
46
46
|
acceptedCount: z.ZodNumber;
|
|
47
47
|
rejectedByUser: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
48
48
|
reasonForRejection: z.ZodString;
|
|
49
|
+
partial: z.ZodOptional<z.ZodObject<{
|
|
50
|
+
accepted: z.ZodNumber;
|
|
51
|
+
total: z.ZodNumber;
|
|
52
|
+
rejectedSegments: z.ZodArray<z.ZodObject<{
|
|
53
|
+
tag: z.ZodString;
|
|
54
|
+
beforeHtml: z.ZodString;
|
|
55
|
+
afterHtml: z.ZodString;
|
|
56
|
+
status: z.ZodEnum<{
|
|
57
|
+
deleted: "deleted";
|
|
58
|
+
matched: "matched";
|
|
59
|
+
inserted: "inserted";
|
|
60
|
+
}>;
|
|
61
|
+
reasonForRejection: z.ZodString;
|
|
62
|
+
}, z.core.$strip>>;
|
|
63
|
+
}, z.core.$strip>>;
|
|
49
64
|
}, z.core.$strip>>>;
|
|
50
65
|
label: z.ZodString;
|
|
51
66
|
agentMessage: z.ZodOptional<z.ZodString>;
|
|
@@ -25,7 +25,7 @@ export default defineBlokkliAgentSystemPrompt({
|
|
|
25
25
|
- The available options change based on various factors, such as the value of other options, the specific state of the paragraph's field values, etc. Always first check which options are available.
|
|
26
26
|
|
|
27
27
|
### EXTRA UX FEATURES
|
|
28
|
-
-
|
|
28
|
+
- To reference a specific paragraph, write its bare UUID inline. For example: "You should rewrite aaaaaaaa-1111-2222-3333-444444444444." The frontend renders the UUID as a clickable chip labelled with the paragraph's bundle. Do **not** wrap the UUID in markdown link syntax \u2014 emit the UUID on its own.
|
|
29
29
|
- You can address the user using the special "${PLACEHOLDER_USER_NAME}" placeholder for a friendly welcome message. This is magically replaced in the frontend with the name of the user!
|
|
30
30
|
|
|
31
31
|
### History and Undo/Redo
|
|
@@ -17,6 +17,7 @@ export default defineBlokkliAgentSystemPrompt({
|
|
|
17
17
|
- The user's first message includes their selection inline as "[User has selected: <bundle> (<uuid>), ...]". Treat that as the target of vague references like "this", "these", "translate this", "make this bigger" \u2014 no extra tool call needed to identify them.
|
|
18
18
|
- For LATER messages where the prompt implies acting on the current selection but the first-message annotation is absent or stale, call "get_selected_paragraphs" \u2014 the user may have changed their selection since the conversation started.
|
|
19
19
|
- You can output text as you please, markdown is allowed!
|
|
20
|
+
- DO NOT use emojis when writing content, unless explicitly told to do so!
|
|
20
21
|
`;
|
|
21
22
|
}
|
|
22
23
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
import type { BlokkliChartData } from '#blokkli/charts/types';
|
|
3
3
|
import type { McpToolContext } from '#blokkli/agent/app/types';
|
|
4
|
-
import type { ColorOption } from '#blokkli/
|
|
4
|
+
import type { ColorOption } from '#blokkli/types/colors';
|
|
5
5
|
export declare const chartTypeEnum: z.ZodEnum<{
|
|
6
6
|
[x: string]: string;
|
|
7
7
|
}>;
|
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { isColorIdValid } from "#blokkli/helpers/colors";
|
|
2
3
|
import { getColorIdAtIndex } from "../../helpers/index.js";
|
|
3
4
|
import { getChartTypeRuntime, getDefaultTypeOptions } from "../../chart-types/index.js";
|
|
4
5
|
import { colorOptions } from "#blokkli-build/editor-config";
|
|
5
6
|
import { definitionIds } from "#blokkli-build/charts-definitions";
|
|
6
7
|
const agentChartTypeIds = definitionIds.filter((id) => id !== "advanced");
|
|
7
8
|
export const chartTypeEnum = z.enum(agentChartTypeIds);
|
|
8
|
-
const colorIds = Object.
|
|
9
|
+
const colorIds = Object.entries(colorOptions).flatMap(([id, option]) => {
|
|
10
|
+
if ("shades" in option) {
|
|
11
|
+
return Object.keys(option.shades).map((shade) => `${id}.${shade}`);
|
|
12
|
+
}
|
|
13
|
+
return [id];
|
|
14
|
+
});
|
|
9
15
|
export const chartColorEnum = z.enum(colorIds);
|
|
10
16
|
export const chartSeriesSchema = z.object({
|
|
11
17
|
name: z.string().describe("Series name (shown in legend)"),
|
|
@@ -89,8 +95,9 @@ export function validateAdvancedConfig(value) {
|
|
|
89
95
|
return { value };
|
|
90
96
|
}
|
|
91
97
|
export function validateChartData(data, options) {
|
|
92
|
-
const
|
|
93
|
-
|
|
98
|
+
const availableIds = options.flatMap(
|
|
99
|
+
(c) => c.shades?.length ? c.shades.map((s) => `${c.id}.${s.id}`) : [c.id]
|
|
100
|
+
);
|
|
94
101
|
for (let i = 0; i < data.series.length; i++) {
|
|
95
102
|
const series = data.series[i];
|
|
96
103
|
if (series.data.length !== data.categories.length) {
|
|
@@ -103,7 +110,7 @@ export function validateChartData(data, options) {
|
|
|
103
110
|
const series = data.series[i];
|
|
104
111
|
if (!series.color) {
|
|
105
112
|
series.color = getColorIdAtIndex(i, options);
|
|
106
|
-
} else if (!
|
|
113
|
+
} else if (!isColorIdValid(series.color, options)) {
|
|
107
114
|
return {
|
|
108
115
|
error: `Invalid color ID "${series.color}" on series "${series.name}". Available colors: ${availableIds.join(", ")}`
|
|
109
116
|
};
|
|
@@ -118,7 +125,7 @@ export function validateChartData(data, options) {
|
|
|
118
125
|
} else {
|
|
119
126
|
for (let i = 0; i < data.categoryColors.length; i++) {
|
|
120
127
|
const id = data.categoryColors[i];
|
|
121
|
-
if (!
|
|
128
|
+
if (!isColorIdValid(id, options)) {
|
|
122
129
|
return {
|
|
123
130
|
error: `Invalid categoryColor ID "${id}" at index ${i}. Available colors: ${availableIds.join(", ")}`
|
|
124
131
|
};
|