@blocknote/xl-ai 0.51.4 → 0.52.1
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/blocknote-xl-ai.cjs +1 -1
- package/dist/blocknote-xl-ai.cjs.map +1 -1
- package/dist/blocknote-xl-ai.js +503 -107
- package/dist/blocknote-xl-ai.js.map +1 -1
- package/dist/locales.cjs.map +1 -1
- package/dist/locales.js.map +1 -1
- package/dist/{server-JIYg7ELG.js → server-CafGbRLa.js} +35 -31
- package/dist/server-CafGbRLa.js.map +1 -0
- package/dist/server-CxZHspeS.cjs +36 -0
- package/dist/server-CxZHspeS.cjs.map +1 -0
- package/dist/server.cjs +1 -1
- package/dist/server.js +1 -2
- package/dist/style.css +1 -1
- package/dist/webpack-stats.json +1 -1
- package/package.json +12 -25
- package/src/AIExtension.ts +12 -7
- package/src/api/formats/base-tools/createAddBlocksTool.ts +4 -4
- package/src/api/formats/base-tools/createUpdateBlockTool.ts +4 -4
- package/src/api/formats/html-blocks/columnContainerDocumentState.test.ts +1 -1
- package/src/api/formats/html-blocks/htmlBlocks.test.ts +6 -8
- package/src/api/formats/html-blocks/tools/getPartialHTML.test.ts +1 -1
- package/src/api/formats/html-blocks/tools/index.ts +15 -21
- package/src/api/formats/html-blocks/tools/rebaseTool.ts +3 -3
- package/src/api/formats/json/errorHandling.test.ts +8 -1
- package/src/api/formats/json/json.test.ts +1 -1
- package/src/api/formats/json/tools/index.ts +4 -4
- package/src/api/formats/json/tools/jsontools.test.ts +1 -1
- package/src/api/formats/markdown-blocks/markdownBlocks.test.ts +1 -1
- package/src/api/formats/markdown-blocks/tools/index.ts +9 -11
- package/src/api/formats/markdown-blocks/tools/rebaseTool.ts +3 -3
- package/src/api/formats/tests/sharedTestCases.ts +2 -3
- package/src/api/formats/tests/snapshotPath.ts +2 -2
- package/src/api/formats/tests/validateTestEnvironment.test.ts +1 -1
- package/src/api/promptHelpers/suffixIds.ts +1 -1
- package/src/api/schema/__snapshots__/schemaToJSONSchema.test.ts.snap +1 -1
- package/src/api/schema/schemaToJSONSchema.test.ts +3 -3
- package/src/api/schema/schemaToJSONSchema.ts +5 -3
- package/src/components/AIMenu/PromptSuggestionMenu.tsx +1 -1
- package/src/plugins/AgentCursorPlugin.ts +8 -1
- package/src/prosemirror/AttributionMarks.ts +204 -0
- package/src/prosemirror/__snapshots__/agent.test.ts.snap +16 -265
- package/src/prosemirror/__snapshots__/rebaseTool.test.ts.snap +4 -4
- package/src/prosemirror/agent.test.ts +8 -10
- package/src/prosemirror/agent.ts +1 -1
- package/src/prosemirror/changeset.test.ts +1 -1
- package/src/prosemirror/fragmentUtil.test.ts +1 -1
- package/src/prosemirror/rebaseTool.test.ts +8 -3
- package/src/server.ts +0 -1
- package/src/streamTool/filterNewOrUpdatedOperations.test.ts +1 -1
- package/src/streamTool/filterValidOperations.test.ts +1 -1
- package/src/streamTool/preprocess.test.ts +1 -1
- package/src/streamTool/toValidatedOperations.test.ts +1 -1
- package/src/streamTool/vercelAiSdk/clientside/ClientSideTransport.ts +8 -5
- package/src/streamTool/vercelAiSdk/util/appendableStream.test.ts +15 -15
- package/src/streamTool/vercelAiSdk/util/chatHandlers.test.ts +10 -1
- package/src/streamTool/vercelAiSdk/util/chatHandlers.ts +7 -7
- package/src/style.css +0 -19
- package/src/testUtil/suggestChangesTestUtil.ts +1 -1
- package/src/util/stream.ts +1 -1
- package/src/vite-env.d.ts +1 -0
- package/types/src/AIExtension.d.ts +4 -0
- package/types/src/api/formats/base-tools/createAddBlocksTool.d.ts +2 -2
- package/types/src/api/formats/base-tools/createUpdateBlockTool.d.ts +2 -2
- package/types/src/api/formats/formats.d.ts +3 -3
- package/types/src/api/formats/html-blocks/tools/rebaseTool.d.ts +2 -2
- package/types/src/api/formats/json/json.d.ts +3 -3
- package/types/src/api/formats/markdown-blocks/tools/rebaseTool.d.ts +2 -2
- package/types/src/api/schema/schemaToJSONSchema.d.ts +3 -3
- package/types/src/prosemirror/AttributionMarks.d.ts +15 -0
- package/types/src/testUtil/cases/editors/blockFormatting.d.ts +17 -17
- package/types/src/testUtil/cases/editors/formattingAndMentions.d.ts +17 -17
- package/types/src/testUtil/cases/editors/simpleEditor.d.ts +51 -51
- package/types/src/testUtil/cases/editors/tables.d.ts +17 -17
- package/types/src/testUtil/cases/schemas/mention.d.ts +17 -17
- package/dist/server-D-Xyj9BS.cjs +0 -36
- package/dist/server-D-Xyj9BS.cjs.map +0 -1
- package/dist/server-JIYg7ELG.js.map +0 -1
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BLOCK_LEVEL_SUGGESTION_GROUP,
|
|
3
|
+
NON_FORMATTING_MARK_GROUP,
|
|
4
|
+
createExtension,
|
|
5
|
+
} from "@blocknote/core";
|
|
6
|
+
import { Mark } from "@tiptap/core";
|
|
7
|
+
import { MarkSpec } from "prosemirror-model";
|
|
8
|
+
|
|
9
|
+
// This copies the marks from @handlewithcare/prosemirror-suggest-changes,
|
|
10
|
+
// but uses the Tiptap Mark API instead so we can use them in BlockNote
|
|
11
|
+
|
|
12
|
+
// The ideal solution would be to not depend on tiptap nodes / marks, but be able to use prosemirror nodes / marks directly
|
|
13
|
+
// this way we could directly use the exported marks from @handlewithcare/prosemirror-suggest-changes
|
|
14
|
+
export const SuggestionAddMark = Mark.create({
|
|
15
|
+
name: "insertion",
|
|
16
|
+
inclusive: false,
|
|
17
|
+
excludes: "deletion modification insertion",
|
|
18
|
+
// Two groups: `BLOCK_LEVEL_SUGGESTION_GROUP` lets the mark sit on block nodes
|
|
19
|
+
// (see core's `suggestionMarks`), so a whole block (e.g. a table row) can be
|
|
20
|
+
// marked as inserted in suggestion mode; `NON_FORMATTING_MARK_GROUP` lets it
|
|
21
|
+
// annotate text inside `"plain"` blocks (e.g. code blocks) — see core's
|
|
22
|
+
// `nonFormattingMarks`.
|
|
23
|
+
group: `${BLOCK_LEVEL_SUGGESTION_GROUP} ${NON_FORMATTING_MARK_GROUP}`,
|
|
24
|
+
addAttributes() {
|
|
25
|
+
return {
|
|
26
|
+
id: { default: null, validate: "number" }, // note: validate is supported in prosemirror but not in tiptap, so this doesn't actually work (considered not critical)
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
extendMarkSchema(extension) {
|
|
30
|
+
if (extension.name !== "insertion") {
|
|
31
|
+
return {};
|
|
32
|
+
}
|
|
33
|
+
return {
|
|
34
|
+
blocknoteIgnore: true,
|
|
35
|
+
inclusive: false,
|
|
36
|
+
|
|
37
|
+
toDOM(mark, inline) {
|
|
38
|
+
return [
|
|
39
|
+
"ins",
|
|
40
|
+
{
|
|
41
|
+
"data-id": String(mark.attrs["id"]),
|
|
42
|
+
"data-inline": String(inline),
|
|
43
|
+
...(!inline && { style: "display: contents" }), // changed to "contents" to make this work for table rows
|
|
44
|
+
},
|
|
45
|
+
0,
|
|
46
|
+
];
|
|
47
|
+
},
|
|
48
|
+
parseDOM: [
|
|
49
|
+
{
|
|
50
|
+
tag: "ins",
|
|
51
|
+
getAttrs(node) {
|
|
52
|
+
if (!node.dataset["id"]) {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
return {
|
|
56
|
+
id: parseInt(node.dataset["id"], 10),
|
|
57
|
+
};
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
],
|
|
61
|
+
} satisfies MarkSpec;
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
export const SuggestionDeleteMark = Mark.create({
|
|
66
|
+
name: "deletion",
|
|
67
|
+
inclusive: false,
|
|
68
|
+
excludes: "insertion modification deletion",
|
|
69
|
+
group: `${BLOCK_LEVEL_SUGGESTION_GROUP} ${NON_FORMATTING_MARK_GROUP}`,
|
|
70
|
+
addAttributes() {
|
|
71
|
+
return {
|
|
72
|
+
id: { default: null, validate: "number" }, // note: validate is supported in prosemirror but not in tiptap
|
|
73
|
+
};
|
|
74
|
+
},
|
|
75
|
+
extendMarkSchema(extension) {
|
|
76
|
+
if (extension.name !== "deletion") {
|
|
77
|
+
return {};
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
blocknoteIgnore: true,
|
|
81
|
+
inclusive: false,
|
|
82
|
+
|
|
83
|
+
// attrs: {
|
|
84
|
+
// id: { validate: "number" },
|
|
85
|
+
// },
|
|
86
|
+
toDOM(mark, inline) {
|
|
87
|
+
return [
|
|
88
|
+
"del",
|
|
89
|
+
{
|
|
90
|
+
"data-id": String(mark.attrs["id"]),
|
|
91
|
+
"data-inline": String(inline),
|
|
92
|
+
...(!inline && { style: "display: contents" }), // changed to "contents" to make this work for table rows
|
|
93
|
+
},
|
|
94
|
+
0,
|
|
95
|
+
];
|
|
96
|
+
},
|
|
97
|
+
parseDOM: [
|
|
98
|
+
{
|
|
99
|
+
tag: "del",
|
|
100
|
+
getAttrs(node) {
|
|
101
|
+
if (!node.dataset["id"]) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
return {
|
|
105
|
+
id: parseInt(node.dataset["id"], 10),
|
|
106
|
+
};
|
|
107
|
+
},
|
|
108
|
+
},
|
|
109
|
+
],
|
|
110
|
+
} satisfies MarkSpec;
|
|
111
|
+
},
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
export const SuggestionModificationMark = Mark.create({
|
|
115
|
+
name: "modification",
|
|
116
|
+
inclusive: false,
|
|
117
|
+
excludes: "deletion insertion",
|
|
118
|
+
group: `${BLOCK_LEVEL_SUGGESTION_GROUP} ${NON_FORMATTING_MARK_GROUP}`,
|
|
119
|
+
addAttributes() {
|
|
120
|
+
// note: validate is supported in prosemirror but not in tiptap
|
|
121
|
+
return {
|
|
122
|
+
id: { default: null, validate: "number" },
|
|
123
|
+
type: { validate: "string" },
|
|
124
|
+
attrName: { default: null, validate: "string|null" },
|
|
125
|
+
previousValue: { default: null },
|
|
126
|
+
newValue: { default: null },
|
|
127
|
+
};
|
|
128
|
+
},
|
|
129
|
+
extendMarkSchema(extension) {
|
|
130
|
+
if (extension.name !== "modification") {
|
|
131
|
+
return {};
|
|
132
|
+
}
|
|
133
|
+
return {
|
|
134
|
+
blocknoteIgnore: true,
|
|
135
|
+
inclusive: false,
|
|
136
|
+
// attrs: {
|
|
137
|
+
// id: { validate: "number" },
|
|
138
|
+
// type: { validate: "string" },
|
|
139
|
+
// attrName: { default: null, validate: "string|null" },
|
|
140
|
+
// previousValue: { default: null },
|
|
141
|
+
// newValue: { default: null },
|
|
142
|
+
// },
|
|
143
|
+
toDOM(mark, inline) {
|
|
144
|
+
return [
|
|
145
|
+
inline ? "span" : "div",
|
|
146
|
+
{
|
|
147
|
+
"data-type": "modification",
|
|
148
|
+
"data-id": String(mark.attrs["id"]),
|
|
149
|
+
"data-mod-type": mark.attrs["type"] as string,
|
|
150
|
+
"data-mod-prev-val": JSON.stringify(mark.attrs["previousValue"]),
|
|
151
|
+
// TODO: Try to serialize marks with toJSON?
|
|
152
|
+
"data-mod-new-val": JSON.stringify(mark.attrs["newValue"]),
|
|
153
|
+
},
|
|
154
|
+
0,
|
|
155
|
+
];
|
|
156
|
+
},
|
|
157
|
+
parseDOM: [
|
|
158
|
+
{
|
|
159
|
+
tag: "span[data-type='modification']",
|
|
160
|
+
getAttrs(node) {
|
|
161
|
+
if (!node.dataset["id"]) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
return {
|
|
165
|
+
id: parseInt(node.dataset["id"], 10),
|
|
166
|
+
type: node.dataset["modType"],
|
|
167
|
+
previousValue: node.dataset["modPrevVal"],
|
|
168
|
+
newValue: node.dataset["modNewVal"],
|
|
169
|
+
};
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
{
|
|
173
|
+
tag: "div[data-type='modification']",
|
|
174
|
+
getAttrs(node) {
|
|
175
|
+
if (!node.dataset["id"]) {
|
|
176
|
+
return false;
|
|
177
|
+
}
|
|
178
|
+
return {
|
|
179
|
+
id: parseInt(node.dataset["id"], 10),
|
|
180
|
+
type: node.dataset["modType"],
|
|
181
|
+
previousValue: node.dataset["modPrevVal"],
|
|
182
|
+
};
|
|
183
|
+
},
|
|
184
|
+
},
|
|
185
|
+
],
|
|
186
|
+
} satisfies MarkSpec;
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Bundles the three AI suggestion marks (`insertion` / `deletion` /
|
|
192
|
+
* `modification`) into a single BlockNote extension, so they can be registered
|
|
193
|
+
* in one line wherever they're needed (the AI extension, or a test that
|
|
194
|
+
* exercises suggestions). The marks opt into being allowed on block nodes via
|
|
195
|
+
* their `blockLevelSuggestion` option — see core's `suggestionMarks`.
|
|
196
|
+
*/
|
|
197
|
+
export const AttributionMarksExtension = createExtension(() => ({
|
|
198
|
+
key: "aiAttributionMarks",
|
|
199
|
+
tiptapExtensions: [
|
|
200
|
+
SuggestionAddMark,
|
|
201
|
+
SuggestionDeleteMark,
|
|
202
|
+
SuggestionModificationMark,
|
|
203
|
+
],
|
|
204
|
+
}));
|