@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
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
"directory": "packages/xl-ai"
|
|
12
12
|
},
|
|
13
13
|
"license": "GPL-3.0 OR PROPRIETARY",
|
|
14
|
-
"version": "0.
|
|
14
|
+
"version": "0.52.1",
|
|
15
15
|
"files": [
|
|
16
16
|
"dist",
|
|
17
17
|
"types",
|
|
@@ -28,7 +28,6 @@
|
|
|
28
28
|
"wysiwyg",
|
|
29
29
|
"rich-text-editor",
|
|
30
30
|
"notion",
|
|
31
|
-
"yjs",
|
|
32
31
|
"block-based",
|
|
33
32
|
"tiptap"
|
|
34
33
|
],
|
|
@@ -63,9 +62,6 @@
|
|
|
63
62
|
"dependencies": {
|
|
64
63
|
"@ai-sdk/provider-utils": "^4.0.2",
|
|
65
64
|
"@ai-sdk/react": "^3.0.5",
|
|
66
|
-
"@blocknote/core": "0.51.4",
|
|
67
|
-
"@blocknote/mantine": "0.51.4",
|
|
68
|
-
"@blocknote/react": "0.51.4",
|
|
69
65
|
"@floating-ui/react": "^0.27.18",
|
|
70
66
|
"@handlewithcare/prosemirror-suggest-changes": "^0.1.8",
|
|
71
67
|
"@tiptap/core": "^3.13.0",
|
|
@@ -78,30 +74,27 @@
|
|
|
78
74
|
"prosemirror-tables": "^1.8.3",
|
|
79
75
|
"prosemirror-transform": "^1.11.0",
|
|
80
76
|
"prosemirror-view": "^1.41.4",
|
|
81
|
-
"
|
|
82
|
-
"react
|
|
83
|
-
"react-icons": "^5.5.0",
|
|
84
|
-
"y-prosemirror": "^1.3.7"
|
|
77
|
+
"@blocknote/core": "^0.52.1",
|
|
78
|
+
"@blocknote/react": "^0.52.1"
|
|
85
79
|
},
|
|
86
80
|
"devDependencies": {
|
|
81
|
+
"react-icons": "^5.5.0",
|
|
87
82
|
"@ai-sdk/anthropic": "^3.0.2",
|
|
88
83
|
"@ai-sdk/google": "^3.0.2",
|
|
89
84
|
"@ai-sdk/groq": "^3.0.2",
|
|
90
85
|
"@ai-sdk/mistral": "^3.0.2",
|
|
91
86
|
"@ai-sdk/openai": "^3.0.2",
|
|
92
87
|
"@ai-sdk/openai-compatible": "^2.0.2",
|
|
93
|
-
"@blocknote/xl-multi-column": "0.51.4",
|
|
94
88
|
"@mswjs/interceptors": "^0.37.6",
|
|
95
89
|
"@types/diff": "^6.0.0",
|
|
96
90
|
"@types/json-diff": "^1.0.3",
|
|
97
91
|
"@types/json-schema": "^7.0.15",
|
|
98
92
|
"@types/lodash.isequal": "^4.5.8",
|
|
99
93
|
"@types/lodash.merge": "^4.6.9",
|
|
94
|
+
"@types/node": "22.13.13",
|
|
100
95
|
"@types/react": "^19.2.3",
|
|
101
96
|
"@types/react-dom": "^19.2.3",
|
|
102
97
|
"@vitejs/plugin-react": "^6.0.1",
|
|
103
|
-
"@vitest/runner": "^4.1.2",
|
|
104
|
-
"eslint": "^8.57.1",
|
|
105
98
|
"glob": "^10.5.0",
|
|
106
99
|
"headers-polyfill": "^4.0.3",
|
|
107
100
|
"msw": "^2.11.5",
|
|
@@ -110,27 +103,21 @@
|
|
|
110
103
|
"rollup-plugin-webpack-stats": "^0.2.6",
|
|
111
104
|
"typescript": "^5.9.3",
|
|
112
105
|
"undici": "^6.22.0",
|
|
113
|
-
"vite": "^8.0.8",
|
|
114
|
-
"vite-plugin-eslint": "^1.8.1",
|
|
115
106
|
"vite-plugin-externalize-deps": "^0.10.0",
|
|
116
|
-
"
|
|
107
|
+
"vite-plus": "^0.1.24",
|
|
108
|
+
"@blocknote/shared": "^0.30.0",
|
|
109
|
+
"@blocknote/xl-multi-column": "^0.52.1"
|
|
117
110
|
},
|
|
118
111
|
"peerDependencies": {
|
|
119
112
|
"react": "^18.0 || ^19.0 || >= 19.0.0-rc",
|
|
120
113
|
"react-dom": "^18.0 || ^19.0 || >= 19.0.0-rc"
|
|
121
114
|
},
|
|
122
|
-
"eslintConfig": {
|
|
123
|
-
"extends": [
|
|
124
|
-
"../../.eslintrc.json"
|
|
125
|
-
]
|
|
126
|
-
},
|
|
127
115
|
"scripts": {
|
|
128
|
-
"dev": "
|
|
129
|
-
"
|
|
130
|
-
"
|
|
131
|
-
"test": "NODE_EXTRA_CA_CERTS=\"$(mkcert -CAROOT)/rootCA.pem\" vitest --run",
|
|
132
|
-
"test-watch": "NODE_EXTRA_CA_CERTS=\"$(mkcert -CAROOT)/rootCA.pem\" vitest watch",
|
|
116
|
+
"dev": "vp dev",
|
|
117
|
+
"lint": "vp lint src",
|
|
118
|
+
"test-watch": "NODE_EXTRA_CA_CERTS=\"$(mkcert -CAROOT)/rootCA.pem\" vp test watch",
|
|
133
119
|
"rename-msw-snapshots": "node scripts/rename-msw-snapshots.mjs",
|
|
120
|
+
"clean": "rimraf dist && rimraf types",
|
|
134
121
|
"email": "email dev"
|
|
135
122
|
}
|
|
136
123
|
}
|
package/src/AIExtension.ts
CHANGED
|
@@ -6,10 +6,8 @@ import {
|
|
|
6
6
|
getNodeById,
|
|
7
7
|
UnreachableCaseError,
|
|
8
8
|
} from "@blocknote/core";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
ShowSelectionExtension,
|
|
12
|
-
} from "@blocknote/core/extensions";
|
|
9
|
+
import { ShowSelectionExtension } from "@blocknote/core/extensions";
|
|
10
|
+
import type { ForkYDocExtension } from "@blocknote/core/yjs";
|
|
13
11
|
import {
|
|
14
12
|
applySuggestions,
|
|
15
13
|
revertSuggestions,
|
|
@@ -22,6 +20,7 @@ import { fixTablesKey } from "prosemirror-tables";
|
|
|
22
20
|
import { buildAIRequest, sendMessageWithAIRequest } from "./api/index.js";
|
|
23
21
|
import { createAgentCursorPlugin } from "./plugins/AgentCursorPlugin.js";
|
|
24
22
|
import { AIRequestHelpers, InvokeAIOptions } from "./types.js";
|
|
23
|
+
import { AttributionMarksExtension } from "./prosemirror/AttributionMarks.js";
|
|
25
24
|
|
|
26
25
|
type AIPluginState = {
|
|
27
26
|
aiMenuState:
|
|
@@ -83,6 +82,7 @@ export const AIExtension = createExtension(
|
|
|
83
82
|
key: "ai",
|
|
84
83
|
options,
|
|
85
84
|
store,
|
|
85
|
+
blockNoteExtensions: [AttributionMarksExtension()],
|
|
86
86
|
mount({ signal }: { signal: AbortSignal }) {
|
|
87
87
|
let scrollInProgress = false;
|
|
88
88
|
// Listens for `scroll` and `scrollend` events to see if a new scroll was
|
|
@@ -220,7 +220,9 @@ export const AIExtension = createExtension(
|
|
|
220
220
|
});
|
|
221
221
|
|
|
222
222
|
// If in collaboration mode, merge the changes back into the original yDoc
|
|
223
|
-
editor
|
|
223
|
+
editor
|
|
224
|
+
.getExtension<typeof ForkYDocExtension>("yForkDoc")
|
|
225
|
+
?.merge({ keepChanges: true });
|
|
224
226
|
|
|
225
227
|
this.closeAIMenu();
|
|
226
228
|
},
|
|
@@ -238,7 +240,9 @@ export const AIExtension = createExtension(
|
|
|
238
240
|
});
|
|
239
241
|
|
|
240
242
|
// If in collaboration mode, discard the changes and revert to the original yDoc
|
|
241
|
-
editor
|
|
243
|
+
editor
|
|
244
|
+
.getExtension<typeof ForkYDocExtension>("yForkDoc")
|
|
245
|
+
?.merge({ keepChanges: false });
|
|
242
246
|
this.closeAIMenu();
|
|
243
247
|
},
|
|
244
248
|
|
|
@@ -379,7 +383,8 @@ export const AIExtension = createExtension(
|
|
|
379
383
|
*/
|
|
380
384
|
async invokeAI(opts: InvokeAIOptions) {
|
|
381
385
|
this.setAIResponseStatus("thinking");
|
|
382
|
-
|
|
386
|
+
// If in collaboration mode, fork the yDoc to allow modifications without affecting the remote
|
|
387
|
+
editor.getExtension<typeof ForkYDocExtension>("yForkDoc")?.fork();
|
|
383
388
|
|
|
384
389
|
try {
|
|
385
390
|
// Create a new AbortController for this request
|
|
@@ -54,7 +54,7 @@ export function createAddBlocksTool<T>(config: {
|
|
|
54
54
|
rebaseTool: (
|
|
55
55
|
id: string,
|
|
56
56
|
editor: BlockNoteEditor<any, any, any>,
|
|
57
|
-
) =>
|
|
57
|
+
) => RebaseTool;
|
|
58
58
|
/**
|
|
59
59
|
* Converts the operation from `AddBlocksToolCall<T>` to `AddBlocksToolCall<PartialBlock<any, any, any>>`
|
|
60
60
|
*
|
|
@@ -68,7 +68,7 @@ export function createAddBlocksTool<T>(config: {
|
|
|
68
68
|
isUpdateToPreviousOperation: boolean;
|
|
69
69
|
isPossiblyPartial: boolean;
|
|
70
70
|
},
|
|
71
|
-
) =>
|
|
71
|
+
) => AddBlocksToolCall<PartialBlock<any, any, any>> | undefined;
|
|
72
72
|
}) {
|
|
73
73
|
return (
|
|
74
74
|
editor: BlockNoteEditor<any, any, any>,
|
|
@@ -196,7 +196,7 @@ export function createAddBlocksTool<T>(config: {
|
|
|
196
196
|
|
|
197
197
|
const operation = chunk.operation as AddBlocksToolCall<T>;
|
|
198
198
|
|
|
199
|
-
const jsonToolCall =
|
|
199
|
+
const jsonToolCall = config.toJSONToolCall(editor, {
|
|
200
200
|
...chunk,
|
|
201
201
|
operation,
|
|
202
202
|
});
|
|
@@ -223,7 +223,7 @@ export function createAddBlocksTool<T>(config: {
|
|
|
223
223
|
let agentSteps: AgentStep[] = [];
|
|
224
224
|
if (i < addedBlockIds.length) {
|
|
225
225
|
// we have already added this block, so we need to update it
|
|
226
|
-
const tool =
|
|
226
|
+
const tool = config.rebaseTool(addedBlockIds[i], editor);
|
|
227
227
|
const steps = updateToReplaceSteps(
|
|
228
228
|
{
|
|
229
229
|
id: addedBlockIds[i],
|
|
@@ -59,7 +59,7 @@ export function createUpdateBlockTool<T>(config: {
|
|
|
59
59
|
rebaseTool: (
|
|
60
60
|
id: string,
|
|
61
61
|
editor: BlockNoteEditor<any, any, any>,
|
|
62
|
-
) =>
|
|
62
|
+
) => RebaseTool;
|
|
63
63
|
/**
|
|
64
64
|
* Converts the operation from `AddBlocksToolCall<T>` to `AddBlocksToolCall<PartialBlock<any, any, any>>`
|
|
65
65
|
*
|
|
@@ -73,7 +73,7 @@ export function createUpdateBlockTool<T>(config: {
|
|
|
73
73
|
isUpdateToPreviousOperation: boolean;
|
|
74
74
|
isPossiblyPartial: boolean;
|
|
75
75
|
},
|
|
76
|
-
) =>
|
|
76
|
+
) => UpdateBlockToolCall<PartialBlock<any, any, any>> | undefined;
|
|
77
77
|
}) {
|
|
78
78
|
return (
|
|
79
79
|
editor: BlockNoteEditor<any, any, any>,
|
|
@@ -202,7 +202,7 @@ export function createUpdateBlockTool<T>(config: {
|
|
|
202
202
|
|
|
203
203
|
// REC: we could investigate whether we can use a single rebasetool across operations instead of
|
|
204
204
|
// creating a new one every time (possibly expensive)
|
|
205
|
-
const tool =
|
|
205
|
+
const tool = config.rebaseTool(operation.id, editor);
|
|
206
206
|
|
|
207
207
|
const fromPos = selectionPositions
|
|
208
208
|
? tool.invertMap.invert().map(selectionPositions.from())
|
|
@@ -212,7 +212,7 @@ export function createUpdateBlockTool<T>(config: {
|
|
|
212
212
|
? tool.invertMap.invert().map(selectionPositions.to())
|
|
213
213
|
: undefined;
|
|
214
214
|
|
|
215
|
-
const jsonToolCall =
|
|
215
|
+
const jsonToolCall = config.toJSONToolCall(editor, {
|
|
216
216
|
...chunk,
|
|
217
217
|
operation,
|
|
218
218
|
});
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import { BlockNoteEditor, BlockNoteSchema } from "@blocknote/core";
|
|
4
4
|
import { withMultiColumn } from "@blocknote/xl-multi-column";
|
|
5
|
-
import { afterEach, beforeEach, describe, expect, it } from "
|
|
5
|
+
import { afterEach, beforeEach, describe, expect, it } from "vite-plus/test";
|
|
6
6
|
|
|
7
7
|
import { htmlBlockLLMFormat } from "./htmlBlocks.js";
|
|
8
8
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { snapshot } from "msw-snapshot";
|
|
2
2
|
import { setupServer } from "msw/node";
|
|
3
3
|
import path from "path";
|
|
4
|
-
import { afterAll, afterEach, beforeAll, describe, it } from "
|
|
4
|
+
import { afterAll, afterEach, beforeAll, describe, it } from "vite-plus/test";
|
|
5
5
|
import { testAIModels } from "../../../testUtil/testAIModels.js";
|
|
6
6
|
|
|
7
7
|
import { BlockNoteEditor } from "@blocknote/core";
|
|
@@ -102,11 +102,8 @@ describe("Models", () => {
|
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
describe("streamToolsProvider", () => {
|
|
105
|
-
it("should return the correct stream tools", () => {
|
|
105
|
+
it.skip("should return the correct stream tools", () => {
|
|
106
106
|
// test skipped, this is only to validate type inference
|
|
107
|
-
return;
|
|
108
|
-
|
|
109
|
-
// eslint-disable-next-line no-unreachable
|
|
110
107
|
const editor = BlockNoteEditor.create();
|
|
111
108
|
const streamTools = htmlBlockLLMFormat
|
|
112
109
|
.getStreamToolsProvider({
|
|
@@ -118,14 +115,14 @@ describe("streamToolsProvider", () => {
|
|
|
118
115
|
|
|
119
116
|
const executor = new StreamToolExecutor(streamTools);
|
|
120
117
|
|
|
121
|
-
executor.executeOne({
|
|
118
|
+
void executor.executeOne({
|
|
122
119
|
type: "add",
|
|
123
120
|
blocks: ["<p>test</p>"],
|
|
124
121
|
referenceId: "1",
|
|
125
122
|
position: "after",
|
|
126
123
|
});
|
|
127
124
|
|
|
128
|
-
executor.executeOne({
|
|
125
|
+
void executor.executeOne({
|
|
129
126
|
// @ts-expect-error
|
|
130
127
|
type: "update",
|
|
131
128
|
blocks: ["<p>test</p>"],
|
|
@@ -133,12 +130,13 @@ describe("streamToolsProvider", () => {
|
|
|
133
130
|
position: "after",
|
|
134
131
|
});
|
|
135
132
|
|
|
136
|
-
executor.executeOne({
|
|
133
|
+
void executor.executeOne({
|
|
137
134
|
type: "add",
|
|
138
135
|
// @ts-expect-error
|
|
139
136
|
blocks: [{ type: "paragraph", content: "test" }],
|
|
140
137
|
referenceId: "1",
|
|
141
138
|
position: "after",
|
|
142
139
|
});
|
|
140
|
+
/* eslint-enable no-unreachable */
|
|
143
141
|
});
|
|
144
142
|
});
|
|
@@ -23,27 +23,21 @@ export const tools = {
|
|
|
23
23
|
},
|
|
24
24
|
validateBlock: validateBlockFunction,
|
|
25
25
|
rebaseTool: createHTMLRebaseTool,
|
|
26
|
-
toJSONToolCall:
|
|
26
|
+
toJSONToolCall: (editor, chunk) => {
|
|
27
27
|
const initialMockID = (window as any).__TEST_OPTIONS?.mockID;
|
|
28
28
|
|
|
29
|
-
const blocks = (
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return block;
|
|
42
|
-
},
|
|
43
|
-
);
|
|
44
|
-
}),
|
|
45
|
-
)
|
|
46
|
-
).flat();
|
|
29
|
+
const blocks = chunk.operation.blocks.flatMap((html) => {
|
|
30
|
+
const parsedHtml = chunk.isPossiblyPartial
|
|
31
|
+
? getPartialHTML(html)
|
|
32
|
+
: html;
|
|
33
|
+
if (!parsedHtml) {
|
|
34
|
+
return [];
|
|
35
|
+
}
|
|
36
|
+
return editor.tryParseHTMLToBlocks(parsedHtml).map((block) => {
|
|
37
|
+
delete (block as any).id;
|
|
38
|
+
return block;
|
|
39
|
+
});
|
|
40
|
+
});
|
|
47
41
|
|
|
48
42
|
// hacky
|
|
49
43
|
if ((window as any).__TEST_OPTIONS) {
|
|
@@ -71,7 +65,7 @@ export const tools = {
|
|
|
71
65
|
},
|
|
72
66
|
validateBlock: validateBlockFunction,
|
|
73
67
|
rebaseTool: createHTMLRebaseTool,
|
|
74
|
-
toJSONToolCall:
|
|
68
|
+
toJSONToolCall: (editor, chunk) => {
|
|
75
69
|
const html = chunk.isPossiblyPartial
|
|
76
70
|
? getPartialHTML(chunk.operation.block)
|
|
77
71
|
: chunk.operation.block;
|
|
@@ -80,7 +74,7 @@ export const tools = {
|
|
|
80
74
|
return undefined;
|
|
81
75
|
}
|
|
82
76
|
|
|
83
|
-
const block =
|
|
77
|
+
const block = editor.tryParseHTMLToBlocks(html)[0];
|
|
84
78
|
|
|
85
79
|
// console.log("update", operation.block);
|
|
86
80
|
// console.log("html", html);
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
rebaseTool,
|
|
6
6
|
} from "../../../../prosemirror/rebaseTool.js";
|
|
7
7
|
|
|
8
|
-
export
|
|
8
|
+
export function createHTMLRebaseTool(
|
|
9
9
|
id: string,
|
|
10
10
|
editor: BlockNoteEditor<any, any, any>,
|
|
11
11
|
) {
|
|
@@ -15,7 +15,7 @@ export async function createHTMLRebaseTool(
|
|
|
15
15
|
throw new Error("block not found");
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
const html =
|
|
18
|
+
const html = editor.blocksToHTMLLossy([
|
|
19
19
|
{
|
|
20
20
|
...block,
|
|
21
21
|
children: [],
|
|
@@ -24,7 +24,7 @@ export async function createHTMLRebaseTool(
|
|
|
24
24
|
|
|
25
25
|
const initialMockID = (window as any).__TEST_OPTIONS?.mockID;
|
|
26
26
|
|
|
27
|
-
const blocks =
|
|
27
|
+
const blocks = editor.tryParseHTMLToBlocks(html);
|
|
28
28
|
|
|
29
29
|
// hacky
|
|
30
30
|
if ((window as any).__TEST_OPTIONS) {
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
afterAll,
|
|
3
|
+
afterEach,
|
|
4
|
+
beforeAll,
|
|
5
|
+
describe,
|
|
6
|
+
expect,
|
|
7
|
+
it,
|
|
8
|
+
} from "vite-plus/test";
|
|
2
9
|
|
|
3
10
|
import { BlockNoteEditor } from "@blocknote/core";
|
|
4
11
|
import { HttpResponse, http } from "msw";
|
|
@@ -19,9 +19,9 @@ export const tools = {
|
|
|
19
19
|
...(blockNoteSchemaToJSONSchema(editor.schema) as any),
|
|
20
20
|
}),
|
|
21
21
|
validateBlock: validateBlockFunction,
|
|
22
|
-
rebaseTool:
|
|
22
|
+
rebaseTool: (_id, editor) =>
|
|
23
23
|
rebaseTool(editor, getApplySuggestionsTr(editor)),
|
|
24
|
-
toJSONToolCall:
|
|
24
|
+
toJSONToolCall: (_editor, chunk) => {
|
|
25
25
|
return chunk.operation;
|
|
26
26
|
},
|
|
27
27
|
}),
|
|
@@ -35,9 +35,9 @@ export const tools = {
|
|
|
35
35
|
...(blockNoteSchemaToJSONSchema(editor.schema) as any),
|
|
36
36
|
}),
|
|
37
37
|
validateBlock: validateBlockFunction,
|
|
38
|
-
rebaseTool:
|
|
38
|
+
rebaseTool: (_id, editor) =>
|
|
39
39
|
rebaseTool(editor, getApplySuggestionsTr(editor)),
|
|
40
|
-
toJSONToolCall:
|
|
40
|
+
toJSONToolCall: (_editor, chunk) => {
|
|
41
41
|
const defaultPropsVals = Object.fromEntries(
|
|
42
42
|
Object.entries(defaultProps).map(([key, val]) => {
|
|
43
43
|
return [key, val.default];
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/* eslint-disable jest/valid-title */
|
|
2
2
|
import { BlockNoteEditor, expandPMRangeToWords } from "@blocknote/core";
|
|
3
|
-
import { describe, expect, it } from "
|
|
3
|
+
import { describe, expect, it } from "vite-plus/test";
|
|
4
4
|
import { addOperationTestCases } from "../../../../testUtil/cases/addOperationTestCases.js";
|
|
5
5
|
import { combinedOperationsTestCases } from "../../../../testUtil/cases/combinedOperationsTestCases.js";
|
|
6
6
|
import { deleteOperationTestCases } from "../../../../testUtil/cases/deleteOperationTestCases.js";
|
|
@@ -24,14 +24,12 @@ export const tools = {
|
|
|
24
24
|
},
|
|
25
25
|
validateBlock: validateBlockFunction,
|
|
26
26
|
rebaseTool: createMDRebaseTool,
|
|
27
|
-
toJSONToolCall:
|
|
28
|
-
const blocks =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}),
|
|
34
|
-
);
|
|
27
|
+
toJSONToolCall: (editor, chunk) => {
|
|
28
|
+
const blocks = chunk.operation.blocks.map((md) => {
|
|
29
|
+
const block = editor.tryParseMarkdownToBlocks(md.trim())[0]; // TODO: trim
|
|
30
|
+
delete (block as any).id;
|
|
31
|
+
return block;
|
|
32
|
+
});
|
|
35
33
|
|
|
36
34
|
// hacky
|
|
37
35
|
if ((window as any).__TEST_OPTIONS) {
|
|
@@ -58,9 +56,9 @@ export const tools = {
|
|
|
58
56
|
},
|
|
59
57
|
validateBlock: validateBlockFunction,
|
|
60
58
|
rebaseTool: createMDRebaseTool,
|
|
61
|
-
toJSONToolCall:
|
|
62
|
-
const block = (
|
|
63
|
-
|
|
59
|
+
toJSONToolCall: (editor, chunk) => {
|
|
60
|
+
const block = editor.tryParseMarkdownToBlocks(
|
|
61
|
+
chunk.operation.block.trim(),
|
|
64
62
|
)[0];
|
|
65
63
|
|
|
66
64
|
delete (block as any).id;
|
|
@@ -6,13 +6,13 @@ import {
|
|
|
6
6
|
rebaseTool,
|
|
7
7
|
} from "../../../../prosemirror/rebaseTool.js";
|
|
8
8
|
|
|
9
|
-
export
|
|
9
|
+
export function createMDRebaseTool(
|
|
10
10
|
id: string,
|
|
11
11
|
editor: BlockNoteEditor<any, any, any>,
|
|
12
12
|
) {
|
|
13
13
|
const tr = getApplySuggestionsTr(editor);
|
|
14
|
-
const md =
|
|
15
|
-
const blocks =
|
|
14
|
+
const md = editor.blocksToMarkdownLossy([getBlock(tr.doc, id)!]);
|
|
15
|
+
const blocks = editor.tryParseMarkdownToBlocks(md);
|
|
16
16
|
|
|
17
17
|
const steps = updateToReplaceSteps(
|
|
18
18
|
{
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { Chat, UIMessage } from "@ai-sdk/react";
|
|
2
2
|
import { BlockNoteEditor } from "@blocknote/core";
|
|
3
|
-
import { getCurrentTest, TestContext } from "@vitest/runner";
|
|
4
3
|
import path from "path";
|
|
5
4
|
import { TextSelection } from "prosemirror-state";
|
|
6
|
-
import { describe, expect, it } from "
|
|
5
|
+
import { describe, expect, it, TestContext, TestRunner } from "vite-plus/test";
|
|
7
6
|
import { AIExtension } from "../../../AIExtension.js";
|
|
8
7
|
import { sendMessageWithAIRequest } from "../../../index.js";
|
|
9
8
|
import { addOperationTestCases } from "../../../testUtil/cases/addOperationTestCases.js";
|
|
@@ -23,7 +22,7 @@ const BASE_FILE_PATH = path.resolve(__dirname, "__snapshots__");
|
|
|
23
22
|
// @ts-expect-error - unused helper kept for debugging snapshots
|
|
24
23
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
25
24
|
async function matchFileSnapshot(data: any, postFix = "") {
|
|
26
|
-
const t = getCurrentTest()!;
|
|
25
|
+
const t = TestRunner.getCurrentTest()!;
|
|
27
26
|
// this uses the same snapshot path, regardless of the model / streaming params
|
|
28
27
|
await expect(data).toMatchFileSnapshot(
|
|
29
28
|
path.resolve(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { getCurrentTest } from "@vitest/runner";
|
|
2
1
|
import { getSortedEntries, toHashString } from "msw-snapshot";
|
|
3
2
|
import path from "node:path";
|
|
3
|
+
import { TestRunner } from "vite-plus/test";
|
|
4
4
|
|
|
5
5
|
async function createRequestHash(req: Request): Promise<string> {
|
|
6
6
|
const url = new URL(req.url);
|
|
@@ -18,7 +18,7 @@ export function createSnapshotPathFn(_basePath: string) {
|
|
|
18
18
|
const fetchCountMap: Record<string, number> = {};
|
|
19
19
|
|
|
20
20
|
return async (info: { request: Request }): Promise<string> => {
|
|
21
|
-
const t = getCurrentTest()!;
|
|
21
|
+
const t = TestRunner.getCurrentTest()!;
|
|
22
22
|
const mswPath = path.join(
|
|
23
23
|
t.suite!.name,
|
|
24
24
|
"__msw_snapshots__",
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { BlockNoteEditor } from "@blocknote/core";
|
|
2
|
-
import { expect, it } from "
|
|
2
|
+
import { expect, it } from "vite-plus/test";
|
|
3
3
|
import { blockNoteSchemaToJSONSchema } from "./schemaToJSONSchema.js";
|
|
4
4
|
|
|
5
|
-
it("creates json schema",
|
|
5
|
+
it("creates json schema", () => {
|
|
6
6
|
// eslint-disable-next-line no-console
|
|
7
7
|
const editor = BlockNoteEditor.create();
|
|
8
8
|
|
|
9
9
|
const jsonSchema = blockNoteSchemaToJSONSchema(editor.schema);
|
|
10
|
-
|
|
10
|
+
expect(jsonSchema).toMatchSnapshot();
|
|
11
11
|
// console.log(JSON.stringify(blockNoteSchemaToJSONSchema(editor.schema), undefined, 2));
|
|
12
12
|
});
|
|
@@ -217,9 +217,11 @@ function blockSchemaToJSONSchema(schema: BlockSchema) {
|
|
|
217
217
|
content:
|
|
218
218
|
val.content === "inline"
|
|
219
219
|
? { $ref: "#/$defs/inlinecontent" }
|
|
220
|
-
: val.content === "
|
|
221
|
-
? { type: "
|
|
222
|
-
:
|
|
220
|
+
: val.content === "plain"
|
|
221
|
+
? { type: "string" }
|
|
222
|
+
: val.content === "table"
|
|
223
|
+
? { type: "object", properties: {} } // TODO
|
|
224
|
+
: undefined,
|
|
223
225
|
// filter out default props (TODO: make option)
|
|
224
226
|
props: propSchemaToJSONSchema(val.propSchema),
|
|
225
227
|
// Object.fromEntries(
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { Plugin, PluginKey } from "prosemirror-state";
|
|
2
2
|
import { Decoration, DecorationSet } from "prosemirror-view";
|
|
3
|
-
|
|
3
|
+
|
|
4
|
+
// Pulled from `y-prosemirror`https://github.com/yjs/y-prosemirror/blob/v1.3.7/src/plugins/cursor-plugin.js
|
|
5
|
+
const defaultSelectionBuilder = (user: { name: string; color: string }) => {
|
|
6
|
+
return {
|
|
7
|
+
style: `background-color: ${user.color}70`,
|
|
8
|
+
class: "ProseMirror-yjs-selection",
|
|
9
|
+
};
|
|
10
|
+
};
|
|
4
11
|
|
|
5
12
|
type AgentCursorState = {
|
|
6
13
|
selection: { anchor: number; head: number } | undefined;
|